1. 安装

1.1. 系统配置:

# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭selinux
sudo sed -i 's/enforcing/disabled/' /etc/selinux/config
# 关闭交换分区
sudo sed -ri 's/.*swap.*/#&/' /etc/fstab
sudo mount -a

1.2. 使用kubeadm安装

#!/usr/bin/env bash

sudo apt update && sudo apt install -y apt-transport-https curl
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update && sudo apt install -y kubelet kubectl kubeadm

# master
sudo kubeadm init --image-repository="registry.cn-hangzhou.aliyuncs.com/google_containers" --kubernetes-version=$(kubeadm version -o short) --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=all
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# network插件
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

# check
kubectl get nodes
kubectl get pods --all-namespaces

# Trouble shooting:
# kubectl -n kube-system describe TYPE NAME

# 创建join token
# kubeadm token create --print-join-command

# 清除安装:
# sudo kubeadm reset -f
# rm -rf ~/.kube

# sh helper:
alias kn='kubectl get nodes -o wide'
alias kp='kubectl get pods --all-namespaces -o wide'
alias kc='kubectl create -f'
alias ka='kubectl apply -f'
alias kr='kubectl replace -f'
alias kt="kubectl -n kube-system describe secret `kubectl -n kube-system get secret | grep admin-user | awk '{print $1}'`"

1.3. 使用Vagrant安装

Vagrantfile
Vagrant.configure("2") do |config|

    config.vm.box = "ubuntu/focal64"
    config.vm.box_check_update = false

    config.vm.define "k8s-master" do |master|
        master.vm.hostname = "k8s-master"
        master.vm.provider "virtualbox" do |vb|
            vb.name = "k8s-master"
            vb.memory = "4096"
            vb.cpus = 2
            vb.gui = false
        end
        master.vm.network "public_network", bridge: "wlp2s0", ip: "192.168.124.110"
        master.vm.provision "shell", path: "./init.sh"
    end

    (1..3).each {|i|
        config.vm.define "k8s-node#{i}" do |node|
            node.vm.hostname = "k8s-node#{i}"
            node.vm.provider "virtualbox" do |vb|
                vb.name = "k8s-node#{i}"
                vb.memory = "4096"
                vb.cpus = 2
                vb.gui = false
            end
            node.vm.network "public_network", bridge: "wlp2s0", ip: "192.168.124.11#{i}"
            node.vm.provision "shell", path: "./init.sh"
        end
    }

end
init.sh
#!/usr/bin/env bash

sudo sed -ri 's/.*swap.*/#&/' /etc/fstab

sudo sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y curl gnupg-agent apt-transport-https ca-certificates software-properties-common
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker vagrant
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://3itj1ym2.mirror.aliyuncs.com"]
}
EOF
sudo sed -i 's/ExecStart.*/& -H tcp:\/\/0.0.0.0:2375/g' /lib/systemd/system/docker.service
sudo chmod 777 /var/run/docker.sock
sudo chmod 777 /etc/docker -R
sudo systemctl daemon-reload
sudo systemctl restart docker
# install docker-compose
sudo wget -q https://soft-1252259164.cos.ap-shanghai.myqcloud.com/docker-compose-1.27.4 -O /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# install kubeadm kubectl kubelet
curl -s https://soft-1252259164.cos.ap-shanghai.myqcloud.com/apt-key.gpg | sudo apt-key add -
echo "deb https://mirrors.ustc.edu.cn/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y kubelet kubectl kubeadm

sudo reboot now
# master节点执行
sudo kubeadm init --image-repository="registry.cn-hangzhou.aliyuncs.com/google_containers" --apiserver-advertise-address="192.168.124.110" --kubernetes-version=$(kubeadm version -o short) --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=all

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

2. 插件安装

2.1. helm

2.1.1. 基本概念

  • Chart: chart用于描述一个安装包

  • Repository: 存放chart的database

  • Release: chart在Kubernetes集群中部署后的一个实例

2.1.2. 安装

curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
helm repo add stable http://mirror.azure.cn/kubernetes/charts/

2.1.3. 常用命令

helm repo list
helm repo add dev https://example.com/dev-charts
helm ls
helm search <chart>
helm inspect [values] <chart>
helm install {CHART|TAR|URL} [--name <name>]
helm delete <chart>
helm create <new_chart>
helm package <chart>

2.2. 安装Dashboard

mkdir certs
openssl req -nodes -newkey rsa:2048 -keyout certs/dashboard.key -out certs/dashboard.csr -subj "/C=/ST=/L=/O=/OU=/CN=kubernetes-dashboard"
openssl x509 -req -sha256 -days 10000 -in certs/dashboard.csr -signkey certs/dashboard.key -out certs/dashboard.crt
kubectl create -f https://soft-1252259164.cos.ap-shanghai.myqcloud.com/dashboard.yml
kubectl create secret generic kubernetes-dashboard-certs --from-file=certs -n kubernetes-dashboard

# 获取登录token
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')

2.3. 集群问题记录

2.3.1. 容器一直部署不上去

  • 检查cpu/内存/磁盘使用量.

  • kubectl describe node <node> 查看node是否被打上了NoSchedule的污点.

  • kubectl describe pod <pod> -n <namespace> 查看pod具体失败原因.

2.3.2. 集群证书过期

Unable to connect to the server: x509: certificate has expired or is not yet valid

sudo kubeadm alpha certs renew all
rm -rf $HOME/.kube
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

3. kubernetes各个组件功能

3.1. Master

集群控制节点,运行以下进程:

  • kube-apiserver: 提供Kubernetes所有资源操作的REST服务

  • kube-controller-manager: 自动化控制所有资源对象

  • kube-scheduler: pod调度

  • kube-proxy: 实现service通信个负载均衡

  • etcd: 保存资源数据

  • coredns

3.2. Node

集群工作负载节点,运行以下进程:

  • kubelet: 负责pod里容器的创建、启动等任务

  • kube-proxy: 实现service通信个负载均衡

  • pause: pod组件

  • docker: 负责本机的容器管理

3.3. Pod

每个pod包含pause容器和多个用户容器. 同一个pod内的容器拥有相同的Network/IPC/UTS[和PID] namespace, 所以它们拥有相同的hostname和network interfaces,但文件系统不同

  • static pod: 设置在node中,并只在该node上运行

  • normal pod: 存储在etcd中,随后会被Master调度到某个node上进行绑定,node上的kubelet进程会实例化一组docker容器运行

3.4. Label Selector

  • kube-controller进程通过RC上定义的labelSelector来筛选需要监控的Pod数量.

  • kube-proxy进程通过service的labelSelector来选择对应的pod, 自动建立起每个service到对应pod的请求路由, 从而实现service的负载均衡.

  • kube-scheduler通过node定义的label和pod定义nodeSelector实现pod的定向调度.

3.5. ReplicationController

定期监控labelSelector匹配的pod副本的数量,确保其等于期望值.
如果修改了一个pod的label, 则RC会自动新起一个pod.如果修改了RC的labelSelector, 则RC会自动创建所有pod副本.

3.6. Replica Set

包含ReplicationController所有的功能, 同时增强了labelSelector的功能.

3.7. DaemonSet

通过nodeSelector在每个节点上运行一个实例

3.8. Job

启动批处理Job, 可以设置任务数/并行数/重试次数等

3.9. CronJob

定时任务: 分/时/日/月/星期

3.10. Deployment

扩展了Replica Set自动scale的功能.

4. kubectl命令

# 获取k8s版本号
kubectl version [-o short]
# 查看所有的api版本号
kubectl api-versions
# 查看 Config metadata
kubectl config view
# 查看集群资源概况
kubectl get [node|ns|po|depoy|cm]
# 查看指定pod中某个容器日志
kubectl logs POD -c CONTAINER
# 创建namespace
kubectl create namespace xxNameSpace

# 设置label
kubectl label po xxPod xxx=xxx [--override]
# 显示label
kubectl get pods --show-labels
# 筛选label
kubectl get pods --show-labels -l env=xxx
# 每个node都会有一些默认label: kubernetes.io/hostname=HOSTNAME

# 编辑
kubectl edit rc RC

# 删除
kubectl delete [TYPE | all] [--all] [-n NAMESPACE]
# 删除rc但保留所有pod
kubectl delete rc RC --cascade=false


# configMap
kubectl create cm CM_NAME --from-file=xxxFile   # xxxFile=CONTENT
kubectl create cm CM_NAME --from-file=xxxDir   # xxxFile1=CONTENT1, xxxFile2=CONTENT2
kubectl create cm CM_NAME --from-literal=a1=v1 --from-literal=a2=v2

# ======部署管理======
# 实现水平扩展
kubectl scale rc <rc_name> [-n <namespace>] --replicas=2
# 部署状态变更状态检查
kubectl rollout status
# 部署历史
kubectl rollout history
# 回滚部署
kubectl rollout undo

5. Pod

5.1. 生命周期:

  1. Pending Pod创建成功,但存在容器还未创建

  2. Running Pod中容器都已成功创建

  3. Succeeded Pod中所有容器均已创建成功

  4. Failed Pod中所有容器均已退出,并且至少有一个退出为失败状态

  5. Unknown 无法获取Pod的状态

5.2. 重启策略

  • Always 容器失效时kubelet自动重启容器

  • OnFailure 容器停止运行且退出码不为0时kubelet自动重启容器

  • Never kubelet不会自动重启容器

    RC和DS必须设置为Always
    Job必须设置为OnFailure或Never

5.3. 健康检查

  • livenessProbe (running)

    如果探测到容器不健康, 则kubelet将杀掉该容器, 并根据容器的重启策略处理
实现方式
  • HTTPGetAction

  • TCPSocketAction

  • ExecAction

  livenessProbe:
    httpGet:
      port: 8080
      path: /actuator/health
    initialDelaySeconds:10 # 首次进行健康检查的延时时长,单位为秒
    timeoutSeconds:2 # 端点超时时长
    periodSeconds:10 # 定时任务
  • readinessProbe (ready)

    请求容器, 如果容器不健康, Endpoint Controller 将从Service的Endpoint中删除该Pod的Endpoint

5.4. 调度

  • Deployment 自动调度

  • NodeSelector 定向调度

    • 给node打标签: kubectl label node <node-name> <label-key>=<label-value>

    • yml配置label: spec.template.spec.nodeSelector

  • NodeAffinity: Node亲和力调度

    • RequiredDuringSchedulingIgnoredDuringExecution: 必须满足指定的规则才可以调度Pod到Node上

    • PreferredDuringSchedulingIgnoredDuringExecution: 优先满足指定规则即可

  • PodAffinity: Pod亲和力调度

  • Taint: kubectl taint node <node-name> <label-key>=<label-value>:<NoSchedule|PreferNoSchedule|NoExecute>

    • NoSchedule: 该节点不会参与调度

    • PreferNoSchedule: 该节点尽量不会参与调度.

    • NoExecute: 该节点不会参与调度, 并且会驱逐该节点上已有的pod.

  • DaemonSet 每个node调度1个Pod

  • Job 批处理调度

  • Cronjob 定时任务

5.5. 升级和回滚

5.5.1. 升级

  • kubectl set image deployment/<deployment-name> <container-name>=<image-name:tag>

  • kubectl edit deployment/<deployment-name>

可以通过spec.strategy.type确定升级方式: RollingUpdate/Recreate

5.5.2. 回滚

查看升级状态: kubectl rollout status deployment/<deployment-name>
查看升级历史: kubectl rollout history deployment/<deployment-name> 创建deployment时加上—​record参数
回滚到指定版本 kubectl rollout undo deployment/<deployment-name> --to-revision=<revision>
暂停/继续更新: kubectl rollout pause/resume deployment/<deployment-name>

5.6. 扩容和缩容

kubectl scale deployment <deployment-name> --replicas <number>

6. Service

6.1. 基本用法:

springboot-svc.yml
apiVersion: v1
kind: Service
metadata:
    name: springboot-demo
spec:
    selector:
        app: springboot-demo
    ports:
    - port: 8081 #service暴露的端口
      targetPort: 8080 #pod端口
kubectl create -f springboot-svc.yml

6.2. Pod间访问

  • 每一个pod中都会有集群中所有service的host/port环境变量. 如 KUBERNETES_SERVICE_HOST/KUBERNETES_SERVICE_PORT 对应名为kubernetes的service

  • 直接通过dns访问: SERVICE[.NAMESPACE.svc.cluster.local], 如 kubia.jy-test.svc.cluster.local

6.3. 暴露外部端口

  • 设置容器级别的hostPort, 将容器应用的端口号映射到物理机上

ports:
- containerPort: 8080
  hostPort: 8081
  • Pod设置hostNetwork=true, 容器中的端口号被映射到物理机上

  • Service设置nodePort映射到物理机,同时设置service的类型为NodePort

    service的nodePort默认范围为30000-32767,可以修改/etc/kubernetes/manifests/kube-apiserver.yaml 添加command `- --service-node-port-range=80-32767`
type: NodePort
ports:
- port: 8080
  targetPort: 8080
  nodePort: 8081
  • 设置service的spec.type为LoadBalancer, 不需要设置NodePort

  • Ingress

7. PV

当集群用户需要在其 pod 中使用持久化存储(PV)时, 他们首先创建持久卷声明 (Persistent VolumeClaim, 简称 PVC) 清单, 指定所需要的最低容量要求和访问模式, 然后用户将PV提交给Kubernetes apiserver, Kubernetes将找到可匹 配的PV并将其绑定到PVC。

8. ConfigMap

8.1. 创建方式

  • 命令行直接创建 kubectl create configmap kubia-config --from-literal=interval=2 --from-literal=foo=bar

  • 从文件(夹)创建 kubectl create configmap kubia-config --from-file=config.conf

  • yaml创建:

demo-cm.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: kubia-cm
  namespace: jy-test
data:
  log.level: debug

8.2. 使用:

envFrom:
  - configMapRef:
      name: kubia-cm
    prefix: log

9. 技能图谱

90af293d7ff8caa58f5ac458a3b03577