├── README.md ├── assets ├── bocker ├── create-k8s-single-node-cluster.sh ├── manifests │ ├── ingress-demo.yaml │ ├── nginx-dpl.yaml │ ├── nginx-lb-dpl.yaml │ └── nginx-lb-svc.yaml ├── scripts │ ├── 01-create-container-manually.sh │ ├── 02-create-unionfs.sh │ ├── 03-docker-use-unionfs.sh │ ├── 04-operate-k8s-object.sh │ └── 05-create-k8s-service.sh └── tools │ └── demo-magic.sh ├── images ├── container-on-the-sea.jpg ├── docker-arch.png ├── k8s-arch.png ├── k8s-full-arch.jpg ├── k8s-ingress-dns-services.png ├── k8s-logo.png ├── k8s-network-model.png ├── k8s-service-lb.png ├── k8s-service-type.webp ├── k8s-storage-arch.png ├── k8s-storage-arch2.png ├── ns-cgroup.png ├── pv-how-to-use.jpeg ├── union-fs.png └── union-fs2.png └── kubernetes简介.md /README.md: -------------------------------------------------------------------------------- 1 | kubernetes分享ppt源文件及相关示例 -------------------------------------------------------------------------------- /assets/bocker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o errexit -o nounset -o pipefail; shopt -s nullglob 3 | btrfs_path='/var/bocker' && cgroups='cpu,cpuacct,memory'; 4 | [[ $# -gt 0 ]] && while [ "${1:0:2}" == '--' ]; do OPTION=${1:2}; [[ $OPTION =~ = ]] && declare "BOCKER_${OPTION/=*/}=${OPTION/*=/}" || declare "BOCKER_${OPTION}=x"; shift; done 5 | 6 | function bocker_check() { 7 | btrfs subvolume list "$btrfs_path" | grep -qw "$1" && echo 0 || echo 1 8 | } 9 | 10 | function bocker_init() { #HELP Create an image from a directory:\nBOCKER init 11 | uuid="img_$(shuf -i 42002-42254 -n 1)" 12 | if [[ -d "$1" ]]; then 13 | [[ "$(bocker_check "$uuid")" == 0 ]] && bocker_run "$@" 14 | btrfs subvolume create "$btrfs_path/$uuid" > /dev/null 15 | cp -rf --reflink=auto "$1"/* "$btrfs_path/$uuid" > /dev/null 16 | [[ ! -f "$btrfs_path/$uuid"/img.source ]] && echo "$1" > "$btrfs_path/$uuid"/img.source 17 | echo "Created: $uuid" 18 | else 19 | echo "No directory named '$1' exists" 20 | fi 21 | } 22 | 23 | function bocker_pull() { #HELP Pull an image from Docker Hub:\nBOCKER pull 24 | 25 | 26 | # @1 获取对应镜像进行拉去, 源代码老版本是v1的docker registry是无效的, 我更新为了v2版本 27 | token=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/$1:pull" | jq '.token'| sed 's/\"//g') 28 | registry_base='https://registry-1.docker.io/v2' 29 | tmp_uuid="$(uuidgen)" && mkdir /tmp/"$tmp_uuid" 30 | 31 | # @2 获取docker镜像每一层的layter,保存到数组中 32 | manifest=$(curl -sL -H "Authorization: Bearer $token" "$registry_base/library/$1/manifests/$2" | jq -r '.fsLayers' | jq -r '.[].blobSum' ) 33 | [[ "${#manifest[@]}" -lt 1 ]] && echo "No image named '$1:$2' exists" && exit 1 34 | 35 | # @3 依次获取镜像每一层, 然后init 36 | for id in ${manifest[@]}; do 37 | curl -#L -H "Authorization: Bearer $token" "$registry_base/library/$1/blobs/$id" -o /tmp/"$tmp_uuid"/layer.tar 38 | tar xf /tmp/"$tmp_uuid"/layer.tar -C /tmp/"$tmp_uuid" 39 | done 40 | echo "$1:$2" > /tmp/"$tmp_uuid"/img.source 41 | bocker_init /tmp/"$tmp_uuid" && rm -rf /tmp/"$tmp_uuid" 42 | } 43 | 44 | function bocker_rm() { #HELP Delete an image or container:\nBOCKER rm 45 | [[ "$(bocker_check "$1")" == 1 ]] && echo "No container named '$1' exists" && exit 1 46 | btrfs subvolume delete "$btrfs_path/$1" > /dev/null 47 | cgdelete -g "$cgroups:/$1" &> /dev/null || true 48 | echo "Removed: $1" 49 | } 50 | 51 | function bocker_images() { #HELP List images:\nBOCKER images 52 | echo -e "IMAGE_ID\t\tSOURCE" 53 | for img in "$btrfs_path"/img_*; do 54 | img=$(basename "$img") 55 | echo -e "$img\t\t$(cat "$btrfs_path/$img/img.source")" 56 | done 57 | } 58 | 59 | function bocker_ps() { #HELP List containers:\nBOCKER ps 60 | echo -e "CONTAINER_ID\t\tCOMMAND" 61 | for ps in "$btrfs_path"/ps_*; do 62 | ps=$(basename "$ps") 63 | echo -e "$ps\t\t$(cat "$btrfs_path/$ps/$ps.cmd")" 64 | done 65 | } 66 | 67 | function bocker_run() { #HELP Create a container:\nBOCKER run 68 | uuid="ps_$(shuf -i 42002-42254 -n 1)" 69 | [[ "$(bocker_check "$1")" == 1 ]] && echo "No image named '$1' exists" && exit 1 70 | [[ "$(bocker_check "$uuid")" == 0 ]] && echo "UUID conflict, retrying..." && bocker_run "$@" && return 71 | cmd="${@:2}" && ip="$(echo "${uuid: -3}" | sed 's/0//g')" && mac="${uuid: -3:1}:${uuid: -2}" 72 | ip link add dev veth0_"$uuid" type veth peer name veth1_"$uuid" 73 | ip link set dev veth0_"$uuid" up 74 | ip link set veth0_"$uuid" master bridge0 75 | ip netns add netns_"$uuid" 76 | ip link set veth1_"$uuid" netns netns_"$uuid" 77 | ip netns exec netns_"$uuid" ip link set dev lo up 78 | ip netns exec netns_"$uuid" ip link set veth1_"$uuid" address 02:42:ac:11:00"$mac" 79 | ip netns exec netns_"$uuid" ip addr add 10.0.0."$ip"/24 dev veth1_"$uuid" 80 | ip netns exec netns_"$uuid" ip link set dev veth1_"$uuid" up 81 | ip netns exec netns_"$uuid" ip route add default via 10.0.0.1 82 | btrfs subvolume snapshot "$btrfs_path/$1" "$btrfs_path/$uuid" > /dev/null 83 | echo 'nameserver 8.8.8.8' > "$btrfs_path/$uuid"/etc/resolv.conf 84 | echo "$cmd" > "$btrfs_path/$uuid/$uuid.cmd" 85 | cgcreate -g "$cgroups:/$uuid" 86 | : "${BOCKER_CPU_SHARE:=512}" && cgset -r cpu.shares="$BOCKER_CPU_SHARE" "$uuid" 87 | : "${BOCKER_MEM_LIMIT:=512}" && cgset -r memory.limit_in_bytes="$((BOCKER_MEM_LIMIT * 1000000))" "$uuid" 88 | cgexec -g "$cgroups:$uuid" \ 89 | ip netns exec netns_"$uuid" \ 90 | unshare -fmuip --mount-proc \ 91 | chroot "$btrfs_path/$uuid" \ 92 | /bin/sh -c "/bin/mount -t proc proc /proc && $cmd" \ 93 | 2>&1 | tee "$btrfs_path/$uuid/$uuid.log" || true 94 | ip link del dev veth0_"$uuid" 95 | ip netns del netns_"$uuid" 96 | } 97 | 98 | function bocker_exec() { #HELP Execute a command in a running container:\nBOCKER exec 99 | [[ "$(bocker_check "$1")" == 1 ]] && echo "No container named '$1' exists" && exit 1 100 | cid="$(ps o ppid,pid | grep "^$(ps o pid,cmd | grep -E "^\ *[0-9]+ unshare.*$1" | awk '{print $1}')" | awk '{print $2}')" 101 | [[ ! "$cid" =~ ^\ *[0-9]+$ ]] && echo "Container '$1' exists but is not running" && exit 1 102 | nsenter -t "$cid" -m -u -i -n -p chroot "$btrfs_path/$1" "${@:2}" 103 | } 104 | 105 | function bocker_logs() { #HELP View logs from a container:\nBOCKER logs 106 | [[ "$(bocker_check "$1")" == 1 ]] && echo "No container named '$1' exists" && exit 1 107 | cat "$btrfs_path/$1/$1.log" 108 | } 109 | 110 | function bocker_commit() { #HELP Commit a container to an image:\nBOCKER commit 111 | [[ "$(bocker_check "$1")" == 1 ]] && echo "No container named '$1' exists" && exit 1 112 | [[ "$(bocker_check "$2")" == 1 ]] && echo "No image named '$2' exists" && exit 1 113 | bocker_rm "$2" && btrfs subvolume snapshot "$btrfs_path/$1" "$btrfs_path/$2" > /dev/null 114 | echo "Created: $2" 115 | } 116 | 117 | function bocker_help() { #HELP Display this message:\nBOCKER help 118 | sed -n "s/^.*#HELP\\s//p;" < "$1" | sed "s/\\\\n/\n\t/g;s/$/\n/;s!BOCKER!${1/!/\\!}!g" 119 | } 120 | 121 | [[ -z "${1-}" ]] && bocker_help "$0" 122 | case $1 in 123 | pull|init|rm|images|ps|run|exec|logs|commit) bocker_"$1" "${@:2}" ;; 124 | *) bocker_help "$0" ;; 125 | esac 126 | -------------------------------------------------------------------------------- /assets/create-k8s-single-node-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 虚拟机的IP及root密码 4 | MASTER_IP=10.211.55.7 5 | ROOT_PASSWD=123456 6 | 7 | # 下载安装介质 8 | wget -c https://sealyun.oss-cn-beijing.aliyuncs.com/latest/sealos && chmod +x sealos && mv sealos /usr/bin 9 | wget -c -O /root/kube1.18.0.tar.gz https://sealyun.oss-cn-beijing.aliyuncs.com/d551b0b9e67e0416d0f9dce870a16665-1.18.0/kube1.18.0.tar.gz 10 | 11 | # 初始化k8s集群 12 | sealos init --master ${MASTER_IP} --user root --passwd ${ROOT_PASSWD} --version v1.18.0 --pkg-url /root/kube1.18.0.tar.gz 13 | 14 | # 去除master节点污点,使master节点可以运行业务Pod 15 | kubectl taint nodes --all node-role.kubernetes.io/master- 16 | 17 | # 开启kubectl命令补全 18 | source <(kubectl completion bash) 19 | echo 'source <(kubectl completion bash)' >> ~/.bashrc -------------------------------------------------------------------------------- /assets/manifests/ingress-demo.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: service-a 5 | spec: 6 | rules: 7 | - host: srva.example.com 8 | http: 9 | paths: 10 | - path: /foo 11 | backend: 12 | serviceName: nginx-a 13 | servicePort: 80 14 | --- 15 | apiVersion: extensions/v1beta1 16 | kind: Ingress 17 | metadata: 18 | name: service-b 19 | spec: 20 | rules: 21 | - host: srvb.example.com 22 | http: 23 | paths: 24 | - path: /foo 25 | backend: 26 | serviceName: nginx-b 27 | servicePort: 80 28 | -------------------------------------------------------------------------------- /assets/manifests/nginx-dpl.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-dpl 5 | labels: 6 | app: nginx 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx 16 | spec: 17 | containers: 18 | - name: nginx 19 | image: nginx:latest 20 | ports: 21 | - containerPort: 80 22 | -------------------------------------------------------------------------------- /assets/manifests/nginx-lb-dpl.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-lb-dpl 5 | labels: 6 | app: nginx 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx 16 | spec: 17 | containers: 18 | - name: nginx 19 | image: nginx:latest 20 | ports: 21 | - containerPort: 80 22 | -------------------------------------------------------------------------------- /assets/manifests/nginx-lb-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-lb-svc 5 | spec: 6 | selector: 7 | app: nginx 8 | ports: 9 | - protocol: TCP 10 | port: 80 11 | targetPort: 80 12 | -------------------------------------------------------------------------------- /assets/scripts/01-create-container-manually.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # include demo-magic 4 | . ../tools/demo-magic.sh -n 5 | 6 | # hide the evidence 7 | clear 8 | 9 | p '# Generate c_uid' 10 | pe 'c_uid="ps_$(shuf -i 42002-42254 -n 1)"' 11 | pe 'echo ${c_uid}' 12 | wait 13 | 14 | p '# Create cgroup' 15 | pe 'cgcreate -g "memory:/${c_uid}"' 16 | wait 17 | 18 | p '# Set cgroup resource limit' 19 | pe 'cgset -r memory.limit_in_bytes="512000000" "${c_uid}"' 20 | wait 21 | 22 | # CID=$(docker run -d python true) 23 | # mkdir -p ../python-image-fs 24 | # docker export $CID | tar -C ../python-image-fs -xf- 25 | p '# Create container by cgroup' 26 | pe 'cgexec -g "memory:${c_uid}" unshare --fork --mount --uts --ipc --pid --mount-proc chroot ../python-image-fs /bin/sh -c "/usr/bin/python3 -m http.server 8080"' 27 | wait 28 | 29 | # ps -ef|grep http.server 30 | # nsenter -t ${pid} --mount --uts --ipc --pid -- /usr/bin/sh 31 | -------------------------------------------------------------------------------- /assets/scripts/02-create-unionfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # include demo-magic 4 | . ../tools/demo-magic.sh -n 5 | 6 | # hide the evidence 7 | clear 8 | 9 | p '# Create dirs' 10 | pe 'mkdir -p ./tmp/lower1 && mkdir -p ./tmp/lower2 && mkdir -p ./tmp/upper && mkdir -p ./tmp/work && mkdir -p ./tmp/merged' 11 | wait 12 | 13 | p '# Create new file in dirs' 14 | pe 'echo "abc" > ./tmp/lower1/abc.txt' 15 | pe 'cat ./tmp/lower1/abc.txt' 16 | wait 17 | pe 'echo "def" > ./tmp/lower2/def.txt' 18 | pe 'cat ./tmp/lower2/def.txt' 19 | wait 20 | 21 | p '# Create unionfs mount' 22 | pe 'mount -t overlay overlay -olowerdir=./tmp/lower1:./tmp/lower2,upperdir=./tmp/upper,workdir=./tmp/work ./tmp/merged' 23 | wait 24 | 25 | p '# Check contents in merged dir' 26 | pe 'ls ./tmp/merged/' 27 | wait 28 | 29 | p '# Create new file to merged dir' 30 | pe 'echo "xyz" > ./tmp/merged/xyz.txt' 31 | wait 32 | 33 | p '# Check contents in upper dir' 34 | pe 'ls ./tmp/upper/' 35 | wait 36 | 37 | p '# Umount merged dir' 38 | pe 'umount ./tmp/merged/' 39 | wait 40 | 41 | -------------------------------------------------------------------------------- /assets/scripts/03-docker-use-unionfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # include demo-magic 4 | . ../tools/demo-magic.sh -n 5 | 6 | # hide the evidence 7 | clear 8 | 9 | p '# Create a docker container' 10 | pe 'docker run -d --name nginx-demo nginx:latest' 11 | wait 12 | 13 | p '# View docker container detail' 14 | pe 'docker inspect nginx-demo' 15 | wait 16 | 17 | p '# Delete a docker container' 18 | pe 'docker rm -f nginx-demo' 19 | wait 20 | -------------------------------------------------------------------------------- /assets/scripts/04-operate-k8s-object.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # include demo-magic 4 | . ../tools/demo-magic.sh -n 5 | 6 | # hide the evidence 7 | clear 8 | 9 | p 'View yaml file' 10 | pe 'cat ../manifests/nginx-dpl.yaml' 11 | wait 12 | 13 | p 'Create k8s deployment object' 14 | pe 'kubectl create -f ../manifests/nginx-dpl.yaml' 15 | wait 16 | 17 | p 'View all k8s deployment object created' 18 | pe 'kubectl get deployments' 19 | wait 20 | 21 | p 'View k8s deployment object created' 22 | pe 'kubectl get deployments nginx-dpl -o wide' 23 | wait 24 | 25 | p 'View k8s deployment object detail' 26 | pe 'kubectl describe deployments nginx-dpl' 27 | wait 28 | 29 | p 'View k8s deployment object detail' 30 | pe 'kubectl get deployments nginx-dpl -o yaml' 31 | wait 32 | 33 | p 'View pods created by the deployment' 34 | pe 'watch kubectl get pods' 35 | wait 36 | 37 | p 'Modify deployment k8s object' 38 | pe 'kubectl edit deployments nginx-dpl' 39 | wait 40 | 41 | p 'View pods created by deployment again' 42 | pe 'watch kubectl get pods' 43 | wait 44 | 45 | p 'Delete deployment k8s object' 46 | pe 'kubectl delete deployments nginx-dpl' 47 | wait 48 | 49 | p 'View pods created by deployment again' 50 | pe 'watch kubectl get pods' 51 | wait 52 | -------------------------------------------------------------------------------- /assets/scripts/05-create-k8s-service.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # include demo-magic 4 | . ../tools/demo-magic.sh -n 5 | 6 | # hide the evidence 7 | clear 8 | 9 | p 'View yaml file' 10 | pe 'cat ../manifests/nginx-lb-dpl.yaml' 11 | wait 12 | 13 | p 'Create k8s deployment object' 14 | pe 'kubectl create -f ../manifests/nginx-lb-dpl.yaml' 15 | wait 16 | 17 | p 'View yaml file' 18 | pe 'cat ../manifests/nginx-lb-svc.yaml' 19 | wait 20 | 21 | p 'Create k8s service object' 22 | pe 'kubectl create -f ../manifests/nginx-lb-svc.yaml' 23 | wait 24 | 25 | p 'View all k8s service object created' 26 | pe 'kubectl get services nginx-lb-svc -o yaml' 27 | wait 28 | 29 | p 'View k8s service object detail' 30 | pe 'kubectl describe services nginx-lb-svc' 31 | wait 32 | 33 | -------------------------------------------------------------------------------- /assets/tools/demo-magic.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################### 4 | # 5 | # demo-magic.sh 6 | # 7 | # Copyright (c) 2015 Paxton Hare 8 | # 9 | # This script lets you script demos in bash. It runs through your demo script when you press 10 | # ENTER. It simulates typing and runs commands. 11 | # 12 | ############################################################################### 13 | 14 | # the speed to "type" the text 15 | TYPE_SPEED=20 16 | 17 | # no wait after "p" or "pe" 18 | NO_WAIT=false 19 | 20 | # if > 0, will pause for this amount of seconds before automatically proceeding with any p or pe 21 | PROMPT_TIMEOUT=0 22 | 23 | # don't show command number unless user specifies it 24 | SHOW_CMD_NUMS=false 25 | 26 | 27 | # handy color vars for pretty prompts 28 | BLACK="\033[0;30m" 29 | BLUE="\033[0;34m" 30 | GREEN="\033[0;32m" 31 | GREY="\033[0;90m" 32 | CYAN="\033[0;36m" 33 | RED="\033[0;31m" 34 | PURPLE="\033[0;35m" 35 | BROWN="\033[0;33m" 36 | WHITE="\033[1;37m" 37 | COLOR_RESET="\033[0m" 38 | 39 | C_NUM=0 40 | 41 | # prompt and command color which can be overriden 42 | DEMO_PROMPT="$ " 43 | DEMO_CMD_COLOR=$WHITE 44 | DEMO_COMMENT_COLOR=$GREY 45 | 46 | ## 47 | # prints the script usage 48 | ## 49 | function usage() { 50 | echo -e "" 51 | echo -e "Usage: $0 [options]" 52 | echo -e "" 53 | echo -e "\tWhere options is one or more of:" 54 | echo -e "\t-h\tPrints Help text" 55 | echo -e "\t-d\tDebug mode. Disables simulated typing" 56 | echo -e "\t-n\tNo wait" 57 | echo -e "\t-w\tWaits max the given amount of seconds before proceeding with demo (e.g. '-w5')" 58 | echo -e "" 59 | } 60 | 61 | ## 62 | # wait for user to press ENTER 63 | # if $PROMPT_TIMEOUT > 0 this will be used as the max time for proceeding automatically 64 | ## 65 | function wait() { 66 | if [[ "$PROMPT_TIMEOUT" == "0" ]]; then 67 | read -rs 68 | else 69 | read -rst "$PROMPT_TIMEOUT" 70 | fi 71 | } 72 | 73 | ## 74 | # print command only. Useful for when you want to pretend to run a command 75 | # 76 | # takes 1 param - the string command to print 77 | # 78 | # usage: p "ls -l" 79 | # 80 | ## 81 | function p() { 82 | if [[ ${1:0:1} == "#" ]]; then 83 | cmd=$DEMO_COMMENT_COLOR$1$COLOR_RESET 84 | else 85 | cmd=$DEMO_CMD_COLOR$1$COLOR_RESET 86 | fi 87 | 88 | # render the prompt 89 | x=$(PS1="$DEMO_PROMPT" "$BASH" --norc -i &1 | sed -n '${s/^\(.*\)exit$/\1/p;}') 90 | 91 | # show command number is selected 92 | if $SHOW_CMD_NUMS; then 93 | printf "[$((++C_NUM))] $x" 94 | else 95 | printf "$x" 96 | fi 97 | 98 | # wait for the user to press a key before typing the command 99 | if !($NO_WAIT); then 100 | wait 101 | fi 102 | 103 | if [[ -z $TYPE_SPEED ]]; then 104 | echo -en "$cmd" 105 | else 106 | echo -en "$cmd" | pv -qL $[$TYPE_SPEED+(-2 + RANDOM%5)]; 107 | fi 108 | 109 | # wait for the user to press a key before moving on 110 | if !($NO_WAIT); then 111 | wait 112 | fi 113 | echo "" 114 | } 115 | 116 | ## 117 | # Prints and executes a command 118 | # 119 | # takes 1 parameter - the string command to run 120 | # 121 | # usage: pe "ls -l" 122 | # 123 | ## 124 | function pe() { 125 | # print the command 126 | p "$@" 127 | 128 | # execute the command 129 | eval "$@" 130 | } 131 | 132 | ## 133 | # Enters script into interactive mode 134 | # 135 | # and allows newly typed commands to be executed within the script 136 | # 137 | # usage : cmd 138 | # 139 | ## 140 | function cmd() { 141 | # render the prompt 142 | x=$(PS1="$DEMO_PROMPT" "$BASH" --norc -i &1 | sed -n '${s/^\(.*\)exit$/\1/p;}') 143 | printf "$x\033[0m" 144 | read command 145 | eval "${command}" 146 | } 147 | 148 | 149 | function check_pv() { 150 | command -v pv >/dev/null 2>&1 || { 151 | 152 | echo "" 153 | echo -e "${RED}##############################################################" 154 | echo "# HOLD IT!! I require pv but it's not installed. Aborting." >&2; 155 | echo -e "${RED}##############################################################" 156 | echo "" 157 | echo -e "${COLOR_RESET}Installing pv:" 158 | echo "" 159 | echo -e "${BLUE}Mac:${COLOR_RESET} $ brew install pv" 160 | echo "" 161 | echo -e "${BLUE}Other:${COLOR_RESET} http://www.ivarch.com/programs/pv.shtml" 162 | echo -e "${COLOR_RESET}" 163 | exit 1; 164 | } 165 | } 166 | 167 | check_pv 168 | # 169 | # handle some default params 170 | # -h for help 171 | # -d for disabling simulated typing 172 | # 173 | while getopts ":dhncw:" opt; do 174 | case $opt in 175 | h) 176 | usage 177 | exit 1 178 | ;; 179 | d) 180 | unset TYPE_SPEED 181 | ;; 182 | n) 183 | NO_WAIT=true 184 | ;; 185 | c) 186 | SHOW_CMD_NUMS=true 187 | ;; 188 | w) 189 | PROMPT_TIMEOUT=$OPTARG 190 | ;; 191 | esac 192 | done 193 | -------------------------------------------------------------------------------- /images/container-on-the-sea.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/container-on-the-sea.jpg -------------------------------------------------------------------------------- /images/docker-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/docker-arch.png -------------------------------------------------------------------------------- /images/k8s-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-arch.png -------------------------------------------------------------------------------- /images/k8s-full-arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-full-arch.jpg -------------------------------------------------------------------------------- /images/k8s-ingress-dns-services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-ingress-dns-services.png -------------------------------------------------------------------------------- /images/k8s-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-logo.png -------------------------------------------------------------------------------- /images/k8s-network-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-network-model.png -------------------------------------------------------------------------------- /images/k8s-service-lb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-service-lb.png -------------------------------------------------------------------------------- /images/k8s-service-type.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-service-type.webp -------------------------------------------------------------------------------- /images/k8s-storage-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-storage-arch.png -------------------------------------------------------------------------------- /images/k8s-storage-arch2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/k8s-storage-arch2.png -------------------------------------------------------------------------------- /images/ns-cgroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/ns-cgroup.png -------------------------------------------------------------------------------- /images/pv-how-to-use.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/pv-how-to-use.jpeg -------------------------------------------------------------------------------- /images/union-fs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/union-fs.png -------------------------------------------------------------------------------- /images/union-fs2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyxu2010/k8s-share/658adb867081b0ee12d2898149007644b38e1964/images/union-fs2.png -------------------------------------------------------------------------------- /kubernetes简介.md: -------------------------------------------------------------------------------- 1 | --- 2 | marp: true 3 | theme: gaia 4 | paginate: true 5 | footer: 'jeremyxu 2020-04-23' 6 | style: | 7 | section a { 8 | font-size: 30px; 9 | } 10 | --- 11 | 12 | 16 | # kubernetes简介 17 | 18 | --- 19 | 20 | ## 目录 21 | ![bg right w:15cm contrast](images/k8s-logo.png) 22 | - 容器技术回顾 23 | - 生产实践中的问题 24 | - kubernetes的架构 25 | - k8s中的常用对象 26 | - k8s中使用网络 27 | - k8s中使用存储卷 28 | - k8s中暴露服务 29 | - 其它实践经验 30 | 31 | --- 32 | ## 容器技术的本质 33 | 容器本质上是一个`集装箱`,它将应用运行依赖的`系统库`、`环境`及`应用程序`本身要包到一起,这样将整个集装箱迁移到另外的环境,可以保证程序`隔离不受干扰地`完美地运行起来。 34 | ![width:30cm height:9cm drop-shadow](images/container-on-the-sea.jpg) 35 | 36 | --- 37 | ## 容器依赖的两大核心技术-内核的隔离技术 38 | ![width:30cm height:7cm drop-shadow](images/ns-cgroup.png) 39 | - Linux通过6大namespace, 就能在OS层面上同时运行多个相互独立的子系统 40 | - Linux通过cgroup技术可以对资源进行划分 41 | 42 | --- 43 | ## 容器依赖的两大核心技术-联合文件系统 44 | ![width:15cm height:11cm drop-shadow](images/union-fs.png)![width:15cm height:11cm drop-shadow](images/union-fs2.png 45 | ) 46 | 47 | --- 48 | ## Docker就是组合的创新 49 | ![w:30cm h:11cm drop-shadow](images/docker-arch.png 50 | ) 51 | [100行bash脚本实现的简易Docker](https://github.com/p8952/bocker/blob/master/bocker) 52 | 53 | --- 54 | ## 生产实践中的问题 55 | - 资源管理、容器调度 56 | - 容器应用的部署、维护和滚动升级 57 | - 容器跨节点通信 58 | - 容器应用的服务发现和负载均衡 59 | - 容器应用的存储卷支持 60 | - 状态监控及自愈 61 | 62 | [为什么kubernetes如此有用?](https://kubernetes.io/zh/docs/concepts/overview/what-is-kubernetes/) 63 | 64 | --- 65 | ## kubernetes的架构 66 | 这次我们换个方式来理解k8s的架构,我们从要解决的问题出发,逐步推导出kubernetes的架构,这样才能印象深刻。 67 | 68 | 问题有N台服务器,想以容器的形式部署某一个业务服务,要求M个副本,如何实现一个`调度系统`完成容器的创建、调度? 69 | 70 | 71 | --- 72 | ## kubernetes的架构-声明式设计 73 | 我们向一个工具描述我们想要让一个事物达到的目标状态,由这个工具自己内部去figure out如何令这个事物达到目标状态。 74 | 75 | 和`Declarative`(声明式设计)相对的是`Imperative`或`Procedural`(过程式设计)。 76 | 77 | 两者的区别是:在`Declarative`中,我们描述的是目标状态`Goal State`,而在`Imperative`模式中,我们描述的是一系列的动作。这一系列的动作如果被正确的顺利执行,最终结果是这个事物达到了我们期望的目标状态的。 78 | 79 | --- 80 | ## kubernetes的架构-我的假想 81 | 如果自己造一个容器编排系统,将从哪里开始: 82 | 83 | - 元数据仓库,用于存储当前的资源信息、目标状态等 84 | - 将存储目标状态转换为实际可调度的单元,并维护目标状态、调度单元的状态 85 | - 进行实际编排的调度器 86 | - 辅助在服务器上执行容器操作的抽象层 87 | - 底层的容器实现 88 | - 接收目标状态、输出当前状态的API接口层服务 89 | 90 | --- 91 | ## kubernetes的架构 92 | ![w:30cm h:12cm drop-shadow](images/k8s-arch.png) 93 | 94 | --- 95 | 100 | ## kubernetes的架构 101 | - etcd: 基于Raft一致性协议的key/value分布式存储,存储k8s的数据和状态信息。 102 | - Controller Manager: 内置了多种控制器(DeploymentController、ServiceController、NodeController等),是Kubernetes维护业务和集群状态的最核心组件。 103 | - Scheduler: 监听apiserver,发现有待调度的Pod,则按照配置的调度策略绑定到合适的Node上,并把绑定信息写入到etcd。 104 | - API Server: 提供了Kubernetes中各种对象(Pod, Deployment, Service等)的Restful接口,Kubernetes中各个组件的通信枢纽。 105 | - Kubelet: 负责Node节点上Pod生命周期管理,包括Pod的创建、销毁、容器监控数据采集、Node状态同步等。 106 | - Kube-proxy: Node节点上的服务网络代理,通过apiserver取到Service、Endpoint等对象信息,根据配置的方式完成服务的反向代理及负载均衡。 107 | - Container Runtime: 底层的容器实现方案,可能是dockerd、containerd, runc等。 108 | 109 | --- 110 | ## k8s常用对象-格式 111 | #### 对象规约(Spec)与状态(Status) 112 | etcd中存储了大量的kubernetes对象,这些对象的格式很类似: 113 | > 每个Kubernetes对象包含两个嵌套的对象字段,它们负责管理对象的配置:对象spec和对象status。 114 | `spec`是必需的,它描述了对象的 期望状态(Desired State) —— 希望对象所具有的特征。 115 | `status`描述了对象的 实际状态(Actual State) ,它是由 Kubernetes 系统提供和更新的。在任何时刻,Kubernetes 控制面一直努力地管理着对象的实际状态以与期望状态相匹配。 116 | 117 | --- 118 | 123 | ## k8s常用对象-分类 124 | 常用的对象分类有以下几种: 125 | - workload类:工作负载类,包括:`pod`、`deployment`、`statefulset`、`daemonset`、`job` 126 | - discovery&loadbalance类:与服务相关,包括:`service`、`endpoint`、`ingress` 127 | - config&storage类:应用初始化配置相关,包括:`configmap`、`secret`、`persistentVolumeClaim` 128 | - cluster类:集群类对象,包括:`Node`、`namespace`、`persitenceVolume`、`serviceAccount`、`clusterRole`、`ClusterRoleVindeing`、`ResoruceQuota` 129 | 130 | --- 131 | ## k8s常用对象-操作 132 | - 增:`kubectl create -f obj-manifest.yaml` 133 | - 删:`kubectl delete -f obj-manifest.yaml` or `kubectl delete ${object-type} ${object-name}` 134 | - 改:`kubectl apply -f obj-manifest.yaml` or `kubectl edit ${object-type} ${object-name}` 135 | - 查:`kubectl get ${object-type} -l ${some-label}` 136 | 137 | --- 138 | ## k8s中使用网络-介入时机 139 | ![w:30cm h:10cm drop-shadow](images/k8s-full-arch.jpg) 140 | `kubelet`调用`Container Runtime`创建好容器后,就要通过`CNI`规范给容器设置好网络 141 | 142 | --- 143 | ## k8s中使用网络-模型规约 144 | - 任意两个pod之间其实是可以直接通信的,无需经过显式地使用NAT来接收数据和地址的转换 145 | - node与pod之间是可以直接通信的,无需使用明显的地址转换 146 | - pod看到自己的IP跟别人看见它所用的 IP 是一样的,中间不能经过转换 147 | 148 | --- 149 | ## k8s中使用网络-模型图示 150 | ![w:30cm h:12cm drop-shadow](images/k8s-network-model.png) 151 | 152 | --- 153 | 158 | ## k8s中使用存储卷-介入时机 159 | ![w:30cm h:10cm drop-shadow](images/pv-how-to-use.jpeg) 160 | 当使用到`persistentVolumeClaim`的工作负载在某个`Node`节点上运行起来时,kubernetes通过`CSI`规范为之创建对应的`persitenceVolume`,并将之挂载到工作负载上。 161 | 162 | --- 163 | ## k8s中使用存储卷-存储架构 164 | ![w:30cm h:12cm drop-shadow](images/k8s-storage-arch.png) 165 | 166 | --- 167 | ## k8s中使用存储卷-存储架构 168 | ![w:30cm h:12cm drop-shadow](images/k8s-storage-arch2.png) 169 | 170 | --- 171 | 176 | ## k8s中使用存储卷-存储架构 177 | 178 | 当需要存储卷时:`Provision->Attach->Mount` 179 | 当不需要存储卷时:`Unmount->Dettach->Delete` 180 | 181 | - `PV Controller`: 负责`PV`/`PVC`的绑定、生命周期管理,并根据需求进行数据卷的`Provision`/`Delete`操作; 182 | - `AD Controller`:负责存储设备的`Attach`/`Detach`操作,将设备挂载到目标节点; 183 | - `Volume Manager`:管理卷的`Mount`/`Unmount`操作、卷设备的格式化以及挂载到一些公用目录上的操作; 184 | - `Volume Plugin`:它主要是对上面所有挂载功能的实现;`PV Controller`、`AD Controller`、`Volume Manager`主要是进行操作的调用,而具体操作则是由`Volume Plugin`实现的。 185 | 186 | --- 187 | ## k8s中暴露业务服务-基于Service的负载均衡 188 | ![w:30cm h:12cm drop-shadow](images/k8s-service-lb.png) 189 | 190 | --- 191 | 196 | ## k8s中暴露业务服务-服务的类型 197 | ![w:10cm h:7cm drop-shadow](images/k8s-service-type.webp) 198 | - `ClusterIP`:使用集群内的私有ip(默认值) 199 | - `NodePort`:除了使用cluster ip外,也将service的port映射到每个node的一个指定内部port上,映射的每个node的内部port都一样 200 | - `LoadBalancer`:使用一个ClusterIP & NodePort,但是会向cloud provider申请映射到service本身的负载均衡 201 | 202 | --- 203 | ## k8s中暴露业务服务-暴露HTTP/HTTPS服务 204 | ![w:30cm h:12cm drop-shadow](images/k8s-ingress-dns-services.png) 205 | 206 | 207 | --- 208 | 214 | ## 总结 215 | kubernetes领域的知识包括很多,而且发展非常快,这里所讲只是冰山一角,其实这里的每个点都可以拿出来单讲,所以本篇只能算一个入门。希望通过此次分享能从心底里理解kubernetes这个容器编排的由来及其大概实现原理,后续的工作中如果涉及到能够心里有底,不慌不怵。 216 | 217 | ### 谢谢 218 | 219 | --- 220 | ## 附录 221 | 1. 快速部署一个kubernetes集群玩一玩,使用工具[sealos](https://github.com/fanux/sealos) 222 | 2. [kubernetes官方文档](https://kubernetes.io/zh/docs/home/) 223 | 3. [kubernetes网页界面](https://kubernetes.io/zh/docs/tasks/access-application-cluster/web-ui-dashboard/) 224 | 4. [tke开源项目](https://github.com/tkestack/tke) 225 | 5. [k8s-share](https://github.com/jeremyxu2010/k8s-share) 226 | 227 | 228 | --------------------------------------------------------------------------------