一、K8S安装篇

1.Kubeadm高可用安装k8s集群

0.网段说明

集群安装时会涉及到三个网段:
宿主机网段:就是安装k8s的服务器
Pod网段:k8s Pod的网段,相当于容器的IP
Service网段:k8s service网段,service用于集群容器通信。

一般service网段会设置为10.96.0.0/12
Pod网段会设置成10.244.0.0/12或者172.16.0.1/12
宿主机网段可能是192.168.0.0/24

需要注意的是这三个网段不能有任何交叉。
比如如果宿主机的IP是10.105.0.x
那么service网段就不能是10.96.0.0/12,因为10.96.0.0/12网段可用IP是:
10.96.0.1 ~ 10.111.255.255
所以10.105是在这个范围之内的,属于网络交叉,此时service网段需要更换,
可以更改为192.168.0.0/16网段(注意如果service网段是192.168开头的子网掩码最好不要是12,最好为16,因为子网掩码是12他的起始IP为192.160.0.1 不是192.168.0.1)。
同样的道理,技术别的网段也不能重复。可以通过http://tools.jb51.net/aideddesign/ip_net_calc/计算:

所以一般的推荐是,直接第一个开头的就不要重复,比如你的宿主机是192开头的,那么你的service可以是10.96.0.0/12.
如果你的宿主机是10开头的,就直接把service的网段改成192.168.0.0/16
如果你的宿主机是172开头的,就直接把pod网段改成192.168.0.0/12

注意搭配,均为10网段、172网段、192网段的搭配,第一个开头数字不一样就免去了网段冲突的可能性,也可以减去计算的步骤。

1.1Kubeadm基础环境配置

1.修改apt源

所有节点配置
vim /etc/apt/sources.list

  1. deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
  2. deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
  3. deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
  4. deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
  5. deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
  6. deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
  7. deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
  8. deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
  9. deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
  10. deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse

ubuntu镜像-ubuntu下载地址-ubuntu安装教程-阿里巴巴开源镜像站 (aliyun.com)

2.修改hosts文件

所有节点配置
vim /etc/hosts

  1. 192.168.68.20 k8s-m01
  2. 192.168.68.21 k8s-m02
  3. 192.168.68.22 k8s-m03
  4. 192.168.68.18 k8s-master-lb # 如果不是高可用集群,该IP为Master01的IP
  5. 192.168.68.23 k8s-n01
  6. 192.168.68.24 k8s-n02
  7. 192.168.68.25 k8s-n03

3.关闭swap分区

所有节点配置
vim /etc/fstab

  1. 临时禁用:swapoff -a
  2. 永久禁用:
  3. vim /etc/fstab 注释掉swap条目,重启系统

4.时间同步

所有节点

  1. apt install ntpdate -y
  2. rm -rf /etc/localtime
  3. ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  4. ntpdate cn.ntp.org.cn
  5. # 加入到crontab -e
  6. */5 * * * * /usr/sbin/ntpdate time2.aliyun.com
  7. # 加入到开机自动同步,vim /etc/rc.local
  8. ntpdate cn.ntp.org.cn

5.配置limit

所有节点
ulimit -SHn 65535
vim /etc/security/limits.conf
# 末尾添加如下内容

  1. * soft nofile 655360
  2. * hard nofile 131072
  3. * soft nproc 655350
  4. * hard nproc 655350
  5. * soft memlock unlimited
  6. * hard memlock unlimited

6.修改内核参数

  1. cat >/etc/sysctl.conf <<EOF
  2. # Controls source route verification
  3. net.ipv4.conf.default.rp_filter = 1
  4. net.ipv4.ip_nonlocal_bind = 1
  5. net.ipv4.ip_forward = 1
  6. # Do not accept source routing
  7. net.ipv4.conf.default.accept_source_route = 0
  8. # Controls the System Request debugging functionality of the kernel
  9. kernel.sysrq = 0
  10. # Controls whether core dumps will append the PID to the core filename.
  11. # Useful for debugging multi-threaded
  12. applications. kernel.core_uses_pid = 1
  13. # Controls the use of TCP syncookies
  14. net.ipv4.tcp_syncookies = 1
  15. # Disable netfilter on bridges.
  16. net.bridge.bridge-nf-call-ip6tables = 0
  17. net.bridge.bridge-nf-call-iptables = 0
  18. net.bridge.bridge-nf-call-arptables = 0
  19. # Controls the default maxmimum size of a mesage queue
  20. kernel.msgmnb = 65536
  21. # # Controls the maximum size of a message, in bytes
  22. kernel.msgmax = 65536
  23. # Controls the maximum shared segment size, in bytes
  24. kernel.shmmax = 68719476736
  25. # # Controls the maximum number of shared memory segments, in pages
  26. kernel.shmall = 4294967296
  27. # TCP kernel paramater
  28. net.ipv4.tcp_mem = 786432 1048576 1572864
  29. net.ipv4.tcp_rmem = 4096 87380 4194304
  30. net.ipv4.tcp_wmem = 4096 16384 4194304 n
  31. et.ipv4.tcp_window_scaling = 1
  32. net.ipv4.tcp_sack = 1
  33. # socket buffer
  34. net.core.wmem_default = 8388608
  35. net.core.rmem_default = 8388608
  36. net.core.rmem_max = 16777216
  37. net.core.wmem_max = 16777216
  38. net.core.netdev_max_backlog = 262144
  39. net.core.somaxconn = 20480
  40. net.core.optmem_max = 81920
  41. # TCP conn
  42. net.ipv4.tcp_max_syn_backlog = 262144
  43. net.ipv4.tcp_syn_retries = 3
  44. net.ipv4.tcp_retries1 = 3
  45. net.ipv4.tcp_retries2 = 15
  46. # tcp conn reuse
  47. net.ipv4.tcp_timestamps = 0
  48. net.ipv4.tcp_tw_reuse = 0
  49. net.ipv4.tcp_tw_recycle = 0
  50. net.ipv4.tcp_fin_timeout = 1
  51. net.ipv4.tcp_max_tw_buckets = 20000
  52. net.ipv4.tcp_max_orphans = 3276800
  53. net.ipv4.tcp_synack_retries = 1
  54. net.ipv4.tcp_syncookies = 1
  55. # keepalive conn
  56. net.ipv4.tcp_keepalive_time = 300
  57. net.ipv4.tcp_keepalive_intvl = 30
  58. net.ipv4.tcp_keepalive_probes = 3
  59. net.ipv4.ip_local_port_range = 10001 65000
  60. # swap
  61. vm.overcommit_memory = 0
  62. vm.swappiness = 10
  63. #net.ipv4.conf.eth1.rp_filter = 0
  64. #net.ipv4.conf.lo.arp_ignore = 1
  65. #net.ipv4.conf.lo.arp_announce = 2
  66. #net.ipv4.conf.all.arp_ignore = 1
  67. #net.ipv4.conf.all.arp_announce = 2
  68. EOF

安装常用软件
apt install wget jq psmisc vim net-tools telnet lvm2 git -y
所有节点安装ipvsadm

  1. apt install ipvsadm ipset conntrack -y
  2. modprobe -- ip_vs
  3. modprobe -- ip_vs_rr
  4. modprobe -- ip_vs_wrr
  5. modprobe -- ip_vs_sh
  6. modprobe -- nf_conntrack
  7. vim /etc/modules-load.d/ipvs.conf
  8. # 加入以下内容
  9. ip_vs
  10. ip_vs_lc
  11. ip_vs_wlc
  12. ip_vs_rr
  13. ip_vs_wrr
  14. ip_vs_lblc
  15. ip_vs_lblcr
  16. ip_vs_dh
  17. ip_vs_sh
  18. ip_vs_fo
  19. ip_vs_nq
  20. ip_vs_sed
  21. ip_vs_ftp
  22. ip_vs_sh
  23. nf_conntrack
  24. ip_tables
  25. ip_set
  26. xt_set
  27. ipt_set
  28. ipt_rpfilter
  29. ipt_REJECT
  30. ipip

然后执行systemctl enable —now systemd-modules-load.service即可
开启一些k8s集群中必须的内核参数,所有节点配置k8s内核

  1. cat <<EOF > /etc/sysctl.d/k8s.conf
  2. net.ipv4.ip_forward = 1
  3. net.bridge.bridge-nf-call-iptables = 1
  4. net.bridge.bridge-nf-call-ip6tables = 1
  5. fs.may_detach_mounts = 1
  6. net.ipv4.conf.all.route_localnet = 1
  7. vm.overcommit_memory=1
  8. vm.panic_on_oom=0
  9. fs.inotify.max_user_watches=89100
  10. fs.file-max=52706963
  11. fs.nr_open=52706963
  12. net.netfilter.nf_conntrack_max=2310720
  13. net.ipv4.tcp_keepalive_time = 600
  14. net.ipv4.tcp_keepalive_probes = 3
  15. net.ipv4.tcp_keepalive_intvl =15
  16. net.ipv4.tcp_max_tw_buckets = 36000
  17. net.ipv4.tcp_tw_reuse = 1
  18. net.ipv4.tcp_max_orphans = 327680
  19. net.ipv4.tcp_orphan_retries = 3
  20. net.ipv4.tcp_syncookies = 1
  21. net.ipv4.tcp_max_syn_backlog = 16384
  22. net.ipv4.ip_conntrack_max = 65536
  23. net.ipv4.tcp_max_syn_backlog = 16384
  24. net.ipv4.tcp_timestamps = 0
  25. net.core.somaxconn = 16384
  26. EOF

sysctl —system
所有节点配置完内核后,重启服务器,保证重启后内核依旧加载
reboot
查看
lsmod | grep —color=auto -e ip_vs -e nf_conntrack

8.Master01节点免密钥登录其他节点

安装过程中生成配置文件和证书均在Master01上操作,集群管理也在Master01上操作,阿里云或者AWS上需要单独一台kubectl服务器。密钥配置如下:
ssh-keygen -t rsa -f /root/.ssh/id_rsa -C "192.168.68.20@k8s-m01" -N ""
for i in k8s-m01 k8s-m02 k8s-m03 k8s-n01 k8s-n02 k8s-n03;do ssh-copy-id -i /root/.ssh/id_rsa.pub $i;done

1.2基本组件安装

1.所有节点安装docker

apt install docker.io -y

提示:
由于新版kubelet建议使用systemd,所以可以把docker的CgroupDriver改成systemd
registry-mirros配置镜像加速

  1. mkdir /etc/docker
  2. cat > /etc/docker/daemon.json <<EOF
  3. {
  4. "exec-opts": ["native.cgroupdriver=systemd"],
  5. "registry-mirrors": ["https://zksmnpbq.mirror.aliyuncs.com"]
  6. }
  7. EOF

设置开机自启
**systemctl daemon-reload && systemctl enable --now docker**

2.所有节点安装k8s组件

apt install kubeadm kubelet kubectl -y
如果无法下载先配置k8s软件源
默认配置的pause镜像使用gcr.io仓库,国内可能无法访问,所以这里配置Kubelet使用阿里云的pause镜像:

  1. # 查看 kubelet 配置
  2. systemctl status kubelet
  3. cd /etc/systemd/system/kubelet.service.d
  4. # 添加 Environment="KUBELET_POD_INFRA_CONTAINER= --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.4.1" 如下
  5. cat 10-kubeadm.conf
  6. # Note: This dropin only works with kubeadm and kubelet v1.11+
  7. [Service]
  8. Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
  9. Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
  10. Environment="KUBELET_CGROUP_ARGS=--system-reserved=memory=10Gi --kube-reserved=memory=400Mi --eviction-hard=imagefs.available<15%,memory.available<300Mi,nodefs.available<10%,nodefs.inodesFree<5% --cgroup-driver=systemd"
  11. Environment="KUBELET_POD_INFRA_CONTAINER= --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.1"
  12. # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
  13. EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
  14. # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
  15. # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
  16. EnvironmentFile=-/etc/sysconfig/kubelet
  17. ExecStart=
  18. ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_CGROUP_ARGS $KUBELET_EXTRA_ARGS
  19. # 重启 kubelet 服务
  20. systemctl daemon-reload
  21. systemctl restart kubelet

3.所有节点安装k8s软件源

  1. apt-get update && apt-get install -y apt-transport-https
  2. curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
  3. vim /etc/apt/sources.list.d/kubernetes.list
  4. deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
  5. apt-get update
  6. apt-get install -y kubelet=1.20.15-00 kubeadm=1.20.15-00 kubectl=1.20.15-00

1.3高可用组件安装

(注意:如果不是高可用集群,haproxy和keepalived无需安装)
公有云要用公有云自带的负载均衡,比如阿里云的SLB,腾讯云的ELB,用来替代haproxy和keepalived,因为公有云大部分都是不支持keepalived的,另外如果用阿里云的话,kubectl控制端不能放在master节点,推荐使用腾讯云,因为阿里云的slb有回环的问题,也就是slb代理的服务器不能反向访问SLB,但是腾讯云修复了这个问题。
所有Master节点通过apt安装HAProxy和KeepAlived:
apt install keepalived haproxy -y
所有Master节点配置HAProxy(详细配置参考HAProxy文档,所有Master节点的HAProxy配置相同):

  1. vim /etc/haproxy/haproxy.cfg
  2. global
  3. maxconn 2000
  4. ulimit-n 16384
  5. log 127.0.0.1 local0 err
  6. stats timeout 30s
  7. defaults
  8. log global
  9. mode http
  10. option httplog
  11. timeout connect 5000
  12. timeout client 50000
  13. timeout server 50000
  14. timeout http-request 15s
  15. timeout http-keep-alive 15s
  16. frontend monitor-in
  17. bind *:33305
  18. mode http
  19. option httplog
  20. monitor-uri /monitor
  21. frontend k8s-master
  22. bind 0.0.0.0:16443
  23. bind 127.0.0.1:16443
  24. mode tcp
  25. option tcplog
  26. tcp-request inspect-delay 5s
  27. default_backend k8s-master
  28. backend k8s-master
  29. mode tcp
  30. option tcplog
  31. option tcp-check
  32. balance roundrobin
  33. default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
  34. server k8s-m01 192.168.68.20:6443 check
  35. server k8s-m02 192.168.68.21:6443 check
  36. server k8s-m03 192.168.68.22:6443 check

所有Master节点配置KeepAlived,配置不一样,注意区分
# vim /etc/keepalived/keepalived.conf ,注意每个节点的IP和网卡(interface参数)
M01节点的配置:

  1. vim /etc/keepalived/keepalived.conf
  2. ! Configuration File for keepalived
  3. global_defs {
  4. router_id LVS_DEVEL
  5. script_user root
  6. enable_script_security
  7. }
  8. vrrp_script chk_apiserver {
  9. script "/etc/keepalived/check_apiserver.sh"
  10. interval 5
  11. weight -5
  12. fall 2
  13. rise 1
  14. }
  15. vrrp_instance VI_1 {
  16. state MASTER
  17. interface ens33
  18. mcast_src_ip 192.168.68.20
  19. virtual_router_id 51
  20. priority 101
  21. advert_int 2
  22. authentication {
  23. auth_type PASS
  24. auth_pass K8SHA_KA_AUTH
  25. }
  26. virtual_ipaddress {
  27. 192.168.68.18
  28. }
  29. track_script {
  30. chk_apiserver
  31. }
  32. }

M02节点的配置:

  1. ! Configuration File for keepalived
  2. global_defs {
  3. router_id LVS_DEVEL
  4. script_user root
  5. enable_script_security
  6. }
  7. vrrp_script chk_apiserver {
  8. script "/etc/keepalived/check_apiserver.sh"
  9. interval 5
  10. weight -5
  11. fall 2
  12. rise 1
  13. }
  14. vrrp_instance VI_1 {
  15. state BACKUP
  16. interface ens33
  17. mcast_src_ip 192.168.68.21
  18. virtual_router_id 51
  19. priority 100
  20. advert_int 2
  21. authentication {
  22. auth_type PASS
  23. auth_pass K8SHA_KA_AUTH
  24. }
  25. virtual_ipaddress {
  26. 192.168.68.18
  27. }
  28. track_script {
  29. chk_apiserver
  30. }
  31. }

M03节点的配置:

  1. ! Configuration File for keepalived
  2. global_defs {
  3. router_id LVS_DEVEL
  4. script_user root
  5. enable_script_security
  6. }
  7. vrrp_script chk_apiserver {
  8. script "/etc/keepalived/check_apiserver.sh"
  9. interval 5
  10. weight -5
  11. fall 2
  12. rise 1
  13. }
  14. vrrp_instance VI_1 {
  15. state BACKUP
  16. interface ens33
  17. mcast_src_ip 192.168.68.22
  18. virtual_router_id 51
  19. priority 100
  20. advert_int 2
  21. authentication {
  22. auth_type PASS
  23. auth_pass K8SHA_KA_AUTH
  24. }
  25. virtual_ipaddress {
  26. 192.168.68.18
  27. }
  28. track_script {
  29. chk_apiserver
  30. }
  31. }

所有master节点配置KeepAlived健康检查文件:

  1. vim /etc/keepalived/check_apiserver.sh
  2. #!/bin/bash
  3. err=0
  4. for k in $(seq 1 3)
  5. do
  6. check_code=$(pgrep haproxy)
  7. if [[ $check_code == "" ]]; then
  8. err=$(expr $err + 1)
  9. sleep 1
  10. continue
  11. else
  12. err=0
  13. break
  14. fi
  15. done
  16. if [[ $err != "0" ]]; then
  17. echo "systemctl stop keepalived"
  18. /usr/bin/systemctl stop keepalived
  19. exit 1
  20. else
  21. exit 0
  22. fi
  23. chmod +x /etc/keepalived/check_apiserver.sh

启动haproxy和keepalived

  1. systemctl daemon-reload
  2. systemctl enable --now haproxy
  3. systemctl enable --now keepalived
  4. systemctl restart keepalived haproxy

重要:如果安装了keepalived和haproxy,需要测试keepalived是否是正常的
测试VIP

  1. root:kubelet.service.d/ # ping 192.168.68.18 -c 4 [11:34:19]
  2. PING 192.168.68.18 (192.168.68.18) 56(84) bytes of data.
  3. 64 bytes from 192.168.68.18: icmp_seq=1 ttl=64 time=0.032 ms
  4. 64 bytes from 192.168.68.18: icmp_seq=2 ttl=64 time=0.043 ms
  5. 64 bytes from 192.168.68.18: icmp_seq=3 ttl=64 time=0.033 ms
  6. 64 bytes from 192.168.68.18: icmp_seq=4 ttl=64 time=0.038 ms
  7. --- 192.168.68.18 ping statistics ---
  8. 4 packets transmitted, 4 received, 0% packet loss, time 3075ms
  9. rtt min/avg/max/mdev = 0.032/0.036/0.043/0.004 ms
  1. root:~/ # telnet 192.168.68.18 16443 [11:44:03]
  2. Trying 192.168.68.18...
  3. Connected to 192.168.68.18.
  4. Escape character is '^]'.
  5. Connection closed by foreign host.

1.4.集群初始化

1.以下操作只在master01节点执行

M01节点创建kubeadm-config.yaml配置文件如下:
Master01:(# 注意,如果不是高可用集群,192.168.68.18:16443改为m01的地址,16443改为apiserver的端口,默认是6443,
注意更改kubernetesVersion的值和自己服务器kubeadm的版本一致:kubeadm version)
注意:以下文件内容,宿主机网段、podSubnet网段、serviceSubnet网段不能重复

  1. apiVersion: kubeadm.k8s.io/v1beta2
  2. bootstrapTokens:
  3. - groups:
  4. - system:bootstrappers:kubeadm:default-node-token
  5. token: 7t2weq.bjbawausm0jaxury
  6. ttl: 24h0m0s
  7. usages:
  8. - signing
  9. - authentication
  10. kind: InitConfiguration
  11. localAPIEndpoint:
  12. advertiseAddress: 192.168.68.20
  13. bindPort: 6443
  14. nodeRegistration:
  15. criSocket: /var/run/dockershim.sock
  16. name: k8s-m01
  17. taints:
  18. - effect: NoSchedule
  19. key: node-role.kubernetes.io/master
  20. ---
  21. apiServer:
  22. certSANs:
  23. - 192.168.68.18
  24. timeoutForControlPlane: 4m0s
  25. apiVersion: kubeadm.k8s.io/v1beta2
  26. certificatesDir: /etc/kubernetes/pki
  27. clusterName: kubernetes
  28. controlPlaneEndpoint: 192.168.68.18:16443
  29. controllerManager: {}
  30. dns:
  31. type: CoreDNS
  32. etcd:
  33. local:
  34. dataDir: /var/lib/etcd
  35. imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
  36. kind: ClusterConfiguration
  37. kubernetesVersion: v1.23.5
  38. networking:
  39. dnsDomain: cluster.local
  40. podSubnet: 172.16.0.0/12
  41. serviceSubnet: 10.96.0.0/16
  42. scheduler: {}

更新kubeadm文件
kubeadm config migrate --old-config kubeadm-config.yaml --new-config new.yaml
将new.yaml文件复制到其他master节点,
for i in k8s-m02 k8s-m03; do scp new.yaml $i:/root/; done
所有Master节点提前下载镜像,可以节省初始化时间(其他节点不需要更改任何配置,包括IP地址也不需要更改):
kubeadm config images pull --config /root/new.yaml

2.所有节点设置开机自启动kubelet

systemctl enable --now kubelet(如果启动失败无需管理,初始化成功以后即可启动)

3.Master01节点初始化

M01节点初始化,初始化以后会在/etc/kubernetes目录下生成对应的证书和配置文件,之后其他Master节点加入M01即可:
kubeadm init --config /root/new.yaml --upload-certs
如果初始化失败,重置后再次初始化,命令如下:
kubeadm reset -f ; ipvsadm --clear ; rm -rf ~/.kube
初始化成功以后,会产生Token值,用于其他节点加入时使用,因此要记录下初始化成功生成的token值(令牌值):

  1. Your Kubernetes control-plane has initialized successfully!
  2. To start using your cluster, you need to run the following as a regular user:
  3. mkdir -p $HOME/.kube
  4. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  5. sudo chown $(id -u):$(id -g) $HOME/.kube/config
  6. Alternatively, if you are the root user, you can run:
  7. export KUBECONFIG=/etc/kubernetes/admin.conf
  8. You should now deploy a pod network to the cluster.
  9. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  10. https://kubernetes.io/docs/concepts/cluster-administration/addons/
  11. You can now join any number of the control-plane node running the following command on each as root:
  12. kubeadm join 192.168.68.18:16443 --token 7t2weq.bjbawausm0jaxury \
  13. --discovery-token-ca-cert-hash sha256:d9c52c2db865df54fd9db22e911ffb7adf12d1244103005fc1885933c6d27673 \
  14. --control-plane --certificate-key 8da0fbf16c11810bb4930846896d21d633af936839c3941890d3c5cf85b98316
  15. Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
  16. As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
  17. "kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
  18. Then you can join any number of worker nodes by running the following on each as root:
  19. kubeadm join 192.168.68.18:16443 --token 7t2weq.bjbawausm0jaxury \
  20. --discovery-token-ca-cert-hash sha256:d9c52c2db865df54fd9db22e911ffb7adf12d1244103005fc1885933c6d27673

4.Master01节点配置环境变量,用于访问Kubernetes集群:

  1. cat <<EOF >> /root/.bashrc
  2. export KUBECONFIG=/etc/kubernetes/admin.conf
  3. EOF
  4. cat <<EOF >> /root/.zshrc
  5. export KUBECONFIG=/etc/kubernetes/admin.conf
  6. EOF

查看节点状态:kubectl get node

采用初始化安装方式,所有的系统组件均以容器的方式运行并且在kube-system命名空间内,此时可以查看Pod状态:kubectl get po -n kube-system

5.配置k8s命令补全

  1. 临时可以使用
  2. apt install -y bash-completion
  3. source /usr/share/bash-completion/bash_completion
  4. source <(kubectl completion bash)
  5. 永久使用
  6. 编辑~/.bashrc
  7. echo "source <(kubectl completion bash)" >>~/.bashrc
  8. vim ~/.bashrc
  9. 添加以下内容
  10. source <(kubectl completion bash)
  11. 保存退出,输入以下命令
  12. source ~/.bashrc

1.Kubectl 自动补全

BASH
  1. apt install -y bash-completion
  2. source <(kubectl completion bash) # 在 bash 中设置当前 shell 的自动补全,要先安装 bash-completion 包。
  3. echo "source <(kubectl completion bash)" >> ~/.bashrc # 在您的 bash shell 中永久的添加自动补全
  4. source ~/.bashrc

您还可以为 kubectl 使用一个速记别名,该别名也可以与 completion 一起使用:

  1. alias k=kubectl
  2. complete -F __start_kubectl k

ZSH
  1. apt install -y bash-completion
  2. source <(kubectl completion zsh) # 在 zsh 中设置当前 shell 的自动补全
  3. echo "[[ $commands[kubectl] ]] && source <(kubectl completion zsh)" >> ~/.zshrc # 在您的 zsh shell 中永久的添加自动补全
  4. source ~/.zshrc

1.5.Master和node节点

注意:以下步骤是上述init命令产生的Token过期了才需要执行以下步骤,如果没有过期不需要执行
Token过期后生成新的token:
kubeadm token create —print-join-command
Master需要生成__—certificate-key
kubeadm init phase upload-certs —upload-certs
Token没有过期直接执行Join就行了
其他master加入集群,master02和master03分别执行

  1. kubeadm join 192.168.68.18:16443 --token 7t2weq.bjbawausm0jaxury \
  2. --discovery-token-ca-cert-hash sha256:d9c52c2db865df54fd9db22e911ffb7adf12d1244103005fc1885933c6d27673 \
  3. --control-plane --certificate-key 8da0fbf16c11810bb4930846896d21d633af936839c3941890d3c5cf85b98316

查看当前状态:kubectl get node
Node节点的配置
Node节点上主要部署公司的一些业务应用,生产环境中不建议Master节点部署系统组件之外的其他Pod,测试环境可以允许Master节点部署Pod以节省系统资源。

  1. kubeadm join 192.168.68.18:16443 --token 7t2weq.bjbawausm0jaxury \
  2. --discovery-token-ca-cert-hash sha256:d9c52c2db865df54fd9db22e911ffb7adf12d1244103005fc1885933c6d27673

所有节点初始化完成后,查看集群状态
kubectl get node

注意,这样集群无法连接访问,需要安装Calico组件

1.6.网络组件Calico组件的安装

calico-etcd.yaml

  1. ---
  2. # Source: calico/templates/calico-etcd-secrets.yaml
  3. # The following contains k8s Secrets for use with a TLS enabled etcd cluster.
  4. # For information on populating Secrets, see http://kubernetes.io/docs/user-guide/secrets/
  5. apiVersion: v1
  6. kind: Secret
  7. type: Opaque
  8. metadata:
  9. name: calico-etcd-secrets
  10. namespace: kube-system
  11. data:
  12. # Populate the following with etcd TLS configuration if desired, but leave blank if
  13. # not using TLS for etcd.
  14. # The keys below should be uncommented and the values populated with the base64
  15. # encoded contents of each file that would be associated with the TLS data.
  16. # Example command for encoding a file contents: cat <file> | base64 -w 0
  17. # etcd-key: null
  18. # etcd-cert: null
  19. # etcd-ca: null
  20. ---
  21. # Source: calico/templates/calico-config.yaml
  22. # This ConfigMap is used to configure a self-hosted Calico installation.
  23. kind: ConfigMap
  24. apiVersion: v1
  25. metadata:
  26. name: calico-config
  27. namespace: kube-system
  28. data:
  29. # Configure this with the location of your etcd cluster.
  30. etcd_endpoints: "http://<ETCD_IP>:<ETCD_PORT>"
  31. # If you're using TLS enabled etcd uncomment the following.
  32. # You must also populate the Secret below with these files.
  33. etcd_ca: "" # "/calico-secrets/etcd-ca"
  34. etcd_cert: "" # "/calico-secrets/etcd-cert"
  35. etcd_key: "" # "/calico-secrets/etcd-key"
  36. # Typha is disabled.
  37. typha_service_name: "none"
  38. # Configure the backend to use.
  39. calico_backend: "bird"
  40. # Configure the MTU to use for workload interfaces and tunnels.
  41. # By default, MTU is auto-detected, and explicitly setting this field should not be required.
  42. # You can override auto-detection by providing a non-zero value.
  43. veth_mtu: "0"
  44. # The CNI network configuration to install on each node. The special
  45. # values in this config will be automatically populated.
  46. cni_network_config: |-
  47. {
  48. "name": "k8s-pod-network",
  49. "cniVersion": "0.3.1",
  50. "plugins": [
  51. {
  52. "type": "calico",
  53. "log_level": "info",
  54. "log_file_path": "/var/log/calico/cni/cni.log",
  55. "etcd_endpoints": "__ETCD_ENDPOINTS__",
  56. "etcd_key_file": "__ETCD_KEY_FILE__",
  57. "etcd_cert_file": "__ETCD_CERT_FILE__",
  58. "etcd_ca_cert_file": "__ETCD_CA_CERT_FILE__",
  59. "mtu": __CNI_MTU__,
  60. "ipam": {
  61. "type": "calico-ipam"
  62. },
  63. "policy": {
  64. "type": "k8s"
  65. },
  66. "kubernetes": {
  67. "kubeconfig": "__KUBECONFIG_FILEPATH__"
  68. }
  69. },
  70. {
  71. "type": "portmap",
  72. "snat": true,
  73. "capabilities": {"portMappings": true}
  74. },
  75. {
  76. "type": "bandwidth",
  77. "capabilities": {"bandwidth": true}
  78. }
  79. ]
  80. }
  81. ---
  82. # Source: calico/templates/calico-kube-controllers-rbac.yaml
  83. # Include a clusterrole for the kube-controllers component,
  84. # and bind it to the calico-kube-controllers serviceaccount.
  85. kind: ClusterRole
  86. apiVersion: rbac.authorization.k8s.io/v1
  87. metadata:
  88. name: calico-kube-controllers
  89. rules:
  90. # Pods are monitored for changing labels.
  91. # The node controller monitors Kubernetes nodes.
  92. # Namespace and serviceaccount labels are used for policy.
  93. - apiGroups: [""]
  94. resources:
  95. - pods
  96. - nodes
  97. - namespaces
  98. - serviceaccounts
  99. verbs:
  100. - watch
  101. - list
  102. - get
  103. # Watch for changes to Kubernetes NetworkPolicies.
  104. - apiGroups: ["networking.k8s.io"]
  105. resources:
  106. - networkpolicies
  107. verbs:
  108. - watch
  109. - list
  110. ---
  111. kind: ClusterRoleBinding
  112. apiVersion: rbac.authorization.k8s.io/v1
  113. metadata:
  114. name: calico-kube-controllers
  115. roleRef:
  116. apiGroup: rbac.authorization.k8s.io
  117. kind: ClusterRole
  118. name: calico-kube-controllers
  119. subjects:
  120. - kind: ServiceAccount
  121. name: calico-kube-controllers
  122. namespace: kube-system
  123. ---
  124. ---
  125. # Source: calico/templates/calico-node-rbac.yaml
  126. # Include a clusterrole for the calico-node DaemonSet,
  127. # and bind it to the calico-node serviceaccount.
  128. kind: ClusterRole
  129. apiVersion: rbac.authorization.k8s.io/v1
  130. metadata:
  131. name: calico-node
  132. rules:
  133. # The CNI plugin needs to get pods, nodes, and namespaces.
  134. - apiGroups: [""]
  135. resources:
  136. - pods
  137. - nodes
  138. - namespaces
  139. verbs:
  140. - get
  141. # EndpointSlices are used for Service-based network policy rule
  142. # enforcement.
  143. - apiGroups: ["discovery.k8s.io"]
  144. resources:
  145. - endpointslices
  146. verbs:
  147. - watch
  148. - list
  149. - apiGroups: [""]
  150. resources:
  151. - endpoints
  152. - services
  153. verbs:
  154. # Used to discover service IPs for advertisement.
  155. - watch
  156. - list
  157. # Pod CIDR auto-detection on kubeadm needs access to config maps.
  158. - apiGroups: [""]
  159. resources:
  160. - configmaps
  161. verbs:
  162. - get
  163. - apiGroups: [""]
  164. resources:
  165. - nodes/status
  166. verbs:
  167. # Needed for clearing NodeNetworkUnavailable flag.
  168. - patch
  169. ---
  170. apiVersion: rbac.authorization.k8s.io/v1
  171. kind: ClusterRoleBinding
  172. metadata:
  173. name: calico-node
  174. roleRef:
  175. apiGroup: rbac.authorization.k8s.io
  176. kind: ClusterRole
  177. name: calico-node
  178. subjects:
  179. - kind: ServiceAccount
  180. name: calico-node
  181. namespace: kube-system
  182. ---
  183. # Source: calico/templates/calico-node.yaml
  184. # This manifest installs the calico-node container, as well
  185. # as the CNI plugins and network config on
  186. # each master and worker node in a Kubernetes cluster.
  187. kind: DaemonSet
  188. apiVersion: apps/v1
  189. metadata:
  190. name: calico-node
  191. namespace: kube-system
  192. labels:
  193. k8s-app: calico-node
  194. spec:
  195. selector:
  196. matchLabels:
  197. k8s-app: calico-node
  198. updateStrategy:
  199. type: RollingUpdate
  200. rollingUpdate:
  201. maxUnavailable: 1
  202. template:
  203. metadata:
  204. labels:
  205. k8s-app: calico-node
  206. spec:
  207. nodeSelector:
  208. kubernetes.io/os: linux
  209. hostNetwork: true
  210. tolerations:
  211. # Make sure calico-node gets scheduled on all nodes.
  212. - effect: NoSchedule
  213. operator: Exists
  214. # Mark the pod as a critical add-on for rescheduling.
  215. - key: CriticalAddonsOnly
  216. operator: Exists
  217. - effect: NoExecute
  218. operator: Exists
  219. serviceAccountName: calico-node
  220. # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force
  221. # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.
  222. terminationGracePeriodSeconds: 0
  223. priorityClassName: system-node-critical
  224. initContainers:
  225. # This container installs the CNI binaries
  226. # and CNI network config file on each node.
  227. - name: install-cni
  228. image: registry.cn-beijing.aliyuncs.com/dotbalo/cni:v3.22.0
  229. command: ["/opt/cni/bin/install"]
  230. envFrom:
  231. - configMapRef:
  232. # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
  233. name: kubernetes-services-endpoint
  234. optional: true
  235. env:
  236. # Name of the CNI config file to create.
  237. - name: CNI_CONF_NAME
  238. value: "10-calico.conflist"
  239. # The CNI network config to install on each node.
  240. - name: CNI_NETWORK_CONFIG
  241. valueFrom:
  242. configMapKeyRef:
  243. name: calico-config
  244. key: cni_network_config
  245. # The location of the etcd cluster.
  246. - name: ETCD_ENDPOINTS
  247. valueFrom:
  248. configMapKeyRef:
  249. name: calico-config
  250. key: etcd_endpoints
  251. # CNI MTU Config variable
  252. - name: CNI_MTU
  253. valueFrom:
  254. configMapKeyRef:
  255. name: calico-config
  256. key: veth_mtu
  257. # Prevents the container from sleeping forever.
  258. - name: SLEEP
  259. value: "false"
  260. volumeMounts:
  261. - mountPath: /host/opt/cni/bin
  262. name: cni-bin-dir
  263. - mountPath: /host/etc/cni/net.d
  264. name: cni-net-dir
  265. - mountPath: /calico-secrets
  266. name: etcd-certs
  267. securityContext:
  268. privileged: true
  269. # Adds a Flex Volume Driver that creates a per-pod Unix Domain Socket to allow Dikastes
  270. # to communicate with Felix over the Policy Sync API.
  271. - name: flexvol-driver
  272. image: registry.cn-beijing.aliyuncs.com/dotbalo/pod2daemon-flexvol:v3.22.0
  273. volumeMounts:
  274. - name: flexvol-driver-host
  275. mountPath: /host/driver
  276. securityContext:
  277. privileged: true
  278. containers:
  279. # Runs calico-node container on each Kubernetes node. This
  280. # container programs network policy and routes on each
  281. # host.
  282. - name: calico-node
  283. image: registry.cn-beijing.aliyuncs.com/dotbalo/node:v3.22.0
  284. envFrom:
  285. - configMapRef:
  286. # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
  287. name: kubernetes-services-endpoint
  288. optional: true
  289. env:
  290. # The location of the etcd cluster.
  291. - name: ETCD_ENDPOINTS
  292. valueFrom:
  293. configMapKeyRef:
  294. name: calico-config
  295. key: etcd_endpoints
  296. # Location of the CA certificate for etcd.
  297. - name: ETCD_CA_CERT_FILE
  298. valueFrom:
  299. configMapKeyRef:
  300. name: calico-config
  301. key: etcd_ca
  302. # Location of the client key for etcd.
  303. - name: ETCD_KEY_FILE
  304. valueFrom:
  305. configMapKeyRef:
  306. name: calico-config
  307. key: etcd_key
  308. # Location of the client certificate for etcd.
  309. - name: ETCD_CERT_FILE
  310. valueFrom:
  311. configMapKeyRef:
  312. name: calico-config
  313. key: etcd_cert
  314. # Set noderef for node controller.
  315. - name: CALICO_K8S_NODE_REF
  316. valueFrom:
  317. fieldRef:
  318. fieldPath: spec.nodeName
  319. # Choose the backend to use.
  320. - name: CALICO_NETWORKING_BACKEND
  321. valueFrom:
  322. configMapKeyRef:
  323. name: calico-config
  324. key: calico_backend
  325. # Cluster type to identify the deployment type
  326. - name: CLUSTER_TYPE
  327. value: "k8s,bgp"
  328. # Auto-detect the BGP IP address.
  329. - name: IP
  330. value: "autodetect"
  331. # Enable IPIP
  332. - name: CALICO_IPV4POOL_IPIP
  333. value: "Always"
  334. # Enable or Disable VXLAN on the default IP pool.
  335. - name: CALICO_IPV4POOL_VXLAN
  336. value: "Never"
  337. # Set MTU for tunnel device used if ipip is enabled
  338. - name: FELIX_IPINIPMTU
  339. valueFrom:
  340. configMapKeyRef:
  341. name: calico-config
  342. key: veth_mtu
  343. # Set MTU for the VXLAN tunnel device.
  344. - name: FELIX_VXLANMTU
  345. valueFrom:
  346. configMapKeyRef:
  347. name: calico-config
  348. key: veth_mtu
  349. # Set MTU for the Wireguard tunnel device.
  350. - name: FELIX_WIREGUARDMTU
  351. valueFrom:
  352. configMapKeyRef:
  353. name: calico-config
  354. key: veth_mtu
  355. # The default IPv4 pool to create on startup if none exists. Pod IPs will be
  356. # chosen from this range. Changing this value after installation will have
  357. # no effect. This should fall within `--cluster-cidr`.
  358. - name: CALICO_IPV4POOL_CIDR
  359. value: "POD_CIDR"
  360. # Disable file logging so `kubectl logs` works.
  361. - name: CALICO_DISABLE_FILE_LOGGING
  362. value: "true"
  363. # Set Felix endpoint to host default action to ACCEPT.
  364. - name: FELIX_DEFAULTENDPOINTTOHOSTACTION
  365. value: "ACCEPT"
  366. # Disable IPv6 on Kubernetes.
  367. - name: FELIX_IPV6SUPPORT
  368. value: "false"
  369. - name: FELIX_HEALTHENABLED
  370. value: "true"
  371. securityContext:
  372. privileged: true
  373. resources:
  374. requests:
  375. cpu: 250m
  376. lifecycle:
  377. preStop:
  378. exec:
  379. command:
  380. - /bin/calico-node
  381. - -shutdown
  382. livenessProbe:
  383. exec:
  384. command:
  385. - /bin/calico-node
  386. - -felix-live
  387. - -bird-live
  388. periodSeconds: 10
  389. initialDelaySeconds: 10
  390. failureThreshold: 6
  391. timeoutSeconds: 10
  392. readinessProbe:
  393. exec:
  394. command:
  395. - /bin/calico-node
  396. - -felix-ready
  397. - -bird-ready
  398. periodSeconds: 10
  399. timeoutSeconds: 10
  400. volumeMounts:
  401. # For maintaining CNI plugin API credentials.
  402. - mountPath: /host/etc/cni/net.d
  403. name: cni-net-dir
  404. readOnly: false
  405. - mountPath: /lib/modules
  406. name: lib-modules
  407. readOnly: true
  408. - mountPath: /run/xtables.lock
  409. name: xtables-lock
  410. readOnly: false
  411. - mountPath: /var/run/calico
  412. name: var-run-calico
  413. readOnly: false
  414. - mountPath: /var/lib/calico
  415. name: var-lib-calico
  416. readOnly: false
  417. - mountPath: /calico-secrets
  418. name: etcd-certs
  419. - name: policysync
  420. mountPath: /var/run/nodeagent
  421. # For eBPF mode, we need to be able to mount the BPF filesystem at /sys/fs/bpf so we mount in the
  422. # parent directory.
  423. - name: sysfs
  424. mountPath: /sys/fs/
  425. # Bidirectional means that, if we mount the BPF filesystem at /sys/fs/bpf it will propagate to the host.
  426. # If the host is known to mount that filesystem already then Bidirectional can be omitted.
  427. mountPropagation: Bidirectional
  428. - name: cni-log-dir
  429. mountPath: /var/log/calico/cni
  430. readOnly: true
  431. volumes:
  432. # Used by calico-node.
  433. - name: lib-modules
  434. hostPath:
  435. path: /lib/modules
  436. - name: var-run-calico
  437. hostPath:
  438. path: /var/run/calico
  439. - name: var-lib-calico
  440. hostPath:
  441. path: /var/lib/calico
  442. - name: xtables-lock
  443. hostPath:
  444. path: /run/xtables.lock
  445. type: FileOrCreate
  446. - name: sysfs
  447. hostPath:
  448. path: /sys/fs/
  449. type: DirectoryOrCreate
  450. # Used to install CNI.
  451. - name: cni-bin-dir
  452. hostPath:
  453. path: /opt/cni/bin
  454. - name: cni-net-dir
  455. hostPath:
  456. path: /etc/cni/net.d
  457. # Used to access CNI logs.
  458. - name: cni-log-dir
  459. hostPath:
  460. path: /var/log/calico/cni
  461. # Mount in the etcd TLS secrets with mode 400.
  462. # See https://kubernetes.io/docs/concepts/configuration/secret/
  463. - name: etcd-certs
  464. secret:
  465. secretName: calico-etcd-secrets
  466. defaultMode: 0400
  467. # Used to create per-pod Unix Domain Sockets
  468. - name: policysync
  469. hostPath:
  470. type: DirectoryOrCreate
  471. path: /var/run/nodeagent
  472. # Used to install Flex Volume Driver
  473. - name: flexvol-driver-host
  474. hostPath:
  475. type: DirectoryOrCreate
  476. path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds
  477. ---
  478. apiVersion: v1
  479. kind: ServiceAccount
  480. metadata:
  481. name: calico-node
  482. namespace: kube-system
  483. ---
  484. # Source: calico/templates/calico-kube-controllers.yaml
  485. # See https://github.com/projectcalico/kube-controllers
  486. apiVersion: apps/v1
  487. kind: Deployment
  488. metadata:
  489. name: calico-kube-controllers
  490. namespace: kube-system
  491. labels:
  492. k8s-app: calico-kube-controllers
  493. spec:
  494. # The controllers can only have a single active instance.
  495. replicas: 1
  496. selector:
  497. matchLabels:
  498. k8s-app: calico-kube-controllers
  499. strategy:
  500. type: Recreate
  501. template:
  502. metadata:
  503. name: calico-kube-controllers
  504. namespace: kube-system
  505. labels:
  506. k8s-app: calico-kube-controllers
  507. spec:
  508. nodeSelector:
  509. kubernetes.io/os: linux
  510. tolerations:
  511. # Mark the pod as a critical add-on for rescheduling.
  512. - key: CriticalAddonsOnly
  513. operator: Exists
  514. - key: node-role.kubernetes.io/master
  515. effect: NoSchedule
  516. serviceAccountName: calico-kube-controllers
  517. priorityClassName: system-cluster-critical
  518. # The controllers must run in the host network namespace so that
  519. # it isn't governed by policy that would prevent it from working.
  520. hostNetwork: true
  521. containers:
  522. - name: calico-kube-controllers
  523. image: registry.cn-beijing.aliyuncs.com/dotbalo/kube-controllers:v3.22.0
  524. env:
  525. # The location of the etcd cluster.
  526. - name: ETCD_ENDPOINTS
  527. valueFrom:
  528. configMapKeyRef:
  529. name: calico-config
  530. key: etcd_endpoints
  531. # Location of the CA certificate for etcd.
  532. - name: ETCD_CA_CERT_FILE
  533. valueFrom:
  534. configMapKeyRef:
  535. name: calico-config
  536. key: etcd_ca
  537. # Location of the client key for etcd.
  538. - name: ETCD_KEY_FILE
  539. valueFrom:
  540. configMapKeyRef:
  541. name: calico-config
  542. key: etcd_key
  543. # Location of the client certificate for etcd.
  544. - name: ETCD_CERT_FILE
  545. valueFrom:
  546. configMapKeyRef:
  547. name: calico-config
  548. key: etcd_cert
  549. # Choose which controllers to run.
  550. - name: ENABLED_CONTROLLERS
  551. value: policy,namespace,serviceaccount,workloadendpoint,node
  552. volumeMounts:
  553. # Mount in the etcd TLS secrets.
  554. - mountPath: /calico-secrets
  555. name: etcd-certs
  556. livenessProbe:
  557. exec:
  558. command:
  559. - /usr/bin/check-status
  560. - -l
  561. periodSeconds: 10
  562. initialDelaySeconds: 10
  563. failureThreshold: 6
  564. timeoutSeconds: 10
  565. readinessProbe:
  566. exec:
  567. command:
  568. - /usr/bin/check-status
  569. - -r
  570. periodSeconds: 10
  571. volumes:
  572. # Mount in the etcd TLS secrets with mode 400.
  573. # See https://kubernetes.io/docs/concepts/configuration/secret/
  574. - name: etcd-certs
  575. secret:
  576. secretName: calico-etcd-secrets
  577. defaultMode: 0440
  578. ---
  579. apiVersion: v1
  580. kind: ServiceAccount
  581. metadata:
  582. name: calico-kube-controllers
  583. namespace: kube-system
  584. ---
  585. # This manifest creates a Pod Disruption Budget for Controller to allow K8s Cluster Autoscaler to evict
  586. apiVersion: policy/v1beta1
  587. kind: PodDisruptionBudget
  588. metadata:
  589. name: calico-kube-controllers
  590. namespace: kube-system
  591. labels:
  592. k8s-app: calico-kube-controllers
  593. spec:
  594. maxUnavailable: 1
  595. selector:
  596. matchLabels:
  597. k8s-app: calico-kube-controllers
  598. ---
  599. # Source: calico/templates/calico-typha.yaml
  600. ---
  601. # Source: calico/templates/configure-canal.yaml
  602. ---
  603. # Source: calico/templates/kdd-crds.yaml

修改calico-etcd.yaml的以下位置
sed -i 's#etcd_endpoints: "http://<ETCD_IP>:<ETCD_PORT>"#etcd_endpoints: "https://192.168.68.20:2379,https://192.168.68.21:2379,https://192.168.68.22:2379"#g' calico-etcd.yaml
ETCD_CA=cat /etc/kubernetes/pki/etcd/ca.crt | base64 | tr -d ‘\n’<br />`ETCD_CERT=`cat /etc/kubernetes/pki/etcd/server.crt | base64 | tr -d '\n'
ETCD_KEY=cat /etc/kubernetes/pki/etcd/server.key | base64 | tr -d ‘\n’<br />`sed -i "s@# etcd-key: null@etcd-key: ${ETCD_KEY}@g; s@# etcd-cert: null@etcd-cert: ${ETCD_CERT}@g; s@# etcd-ca: null@etcd-ca: ${ETCD_CA}@g" calico-etcd.yaml`<br />`sed -i 's#etcd_ca: ""#etcd_ca: "/calico-secrets/etcd-ca"#g; s#etcd_cert: ""#etcd_cert: "/calico-secrets/etcd-cert"#g; s#etcd_key: "" #etcd_key: "/calico-secrets/etcd-key" #g' calico-etcd.yaml`<br />`POD_SUBNET=`cat /etc/kubernetes/manifests/kube-controller-manager.yaml | grep cluster-cidr= | awk -F= '{print $NF}'
sed -i 's@# - name: CALICO_IPV4POOL_CIDR@- name: CALICO_IPV4POOL_CIDR@g; s@# value: "172.16.0.0/12"@ value: '"${POD_SUBNET}"'@g' calico-etcd.yaml
kubectl apply -f calico-etcd.yaml
部署calico 时报错,下载的官方的calico.yaml 文件 【数据存储在Kubernetes API Datastore服务中】https://docs.projectcalico.org/manifests/calico.yaml
报错内容:
Warning: policy/v1beta1 PodDisruptionBudget is deprecated in v1.21+, unavailable in v1.25+; use policy/v1 PodDisruptionBudget
解决方法: 其实报错很很明显了 calico.yaml 文件里的 用的是 v1beta1 PodDisruptionBudget ,而在K8S 1.21 版本之后就不支持v1beta1 PodDisruptionBudget ,改为支持
v1 PodDisruptionBudget

使用 Kubernetes API 数据存储安装 Calico,50 个节点或更少
1.下载 Kubernetes API 数据存储的 Calico 网络清单。
curl https://docs.projectcalico.org/manifests/calico.yaml -O
2.如果您使用的是 Pod CIDR ,请跳到下一步。如果您将不同的 pod CIDR 与 kubeadm 配合使用,则无需进行任何更改 - Calico 将根据正在运行的配置自动检测 CIDR。对于其他平台,请确保取消对清单中CALICO_IPV4POOL_CIDR变量的注释,并将其设置为与所选 pod CIDR 相同的值。192.168.0.0/16

  1. - name: CALICO_IPV4POOL_CIDR
  2. value: "172.16.0.0/12"
  3. 修改calico.yaml取消注释,
  4. valuepodSubnet一样

3.根据需要自定义清单。
4.使用以下命令应用清单。
kubectl apply -f calico.yaml

使用 Kubernetes API 数据存储安装 Calico,超过 50 个节点

  1. 下载 Kubernetes API 数据存储的 Calico 网络清单。
  2. $ curl https://docs.projectcalico.org/manifests/calico-typha.yaml -o calico.yaml
  3. 如果您使用的是 Pod CIDR ,请跳到下一步。如果您将不同的 pod CIDR 与 kubeadm 配合使用,则无需进行任何更改 - Calico 将根据正在运行的配置自动检测 CIDR。对于其他平台,请确保取消对清单中CALICO_IPV4POOL_CIDR变量的注释,并将其设置为与所选 pod CIDR 相同的值。192.168.0.0/16
  4. 将副本计数修改为命名 中的所需数字。Deploymentcalico-typha
  5. apiVersion: apps/v1beta1 kind: Deployment metadata: name: calico-typha … spec: … replicas:
  6. 我们建议每 200 个节点至少一个副本,并且不超过 20 个副本。在生产环境中,我们建议至少使用三个副本,以减少滚动升级和故障的影响。副本数应始终小于节点数,否则滚动升级将停止。此外,Typha 仅当 Typha 实例数少于节点数时,才有助于扩展。
  7. 警告:如果将 Typha 部署副本计数设置为 0,则 Felix 将不会启动。typha_service_name
  8. 如果需要,自定义清单。
  9. 应用清单。
  10. $ kubectl apply -f calico.yaml

使用 etcd 数据存储安装 Calico
注意:不建议将etcd数据库用于新安装。但是,如果您将Calico作为OpenStack和Kubernetes的网络插件运行,则可以选择它。

  1. 下载 etcd 的 Calico 网络清单。
  2. $ curl https://docs.projectcalico.org/manifests/calico-etcd.yaml -o calico.yaml
  3. 如果您使用的是 Pod CIDR ,请跳到下一步。如果您将不同的 pod CIDR 与 kubeadm 配合使用,则无需进行任何更改 - Calico 将根据正在运行的配置自动检测 CIDR。对于其他平台,请确保取消对清单中CALICO_IPV4POOL_CIDR变量的注释,并将其设置为与所选 pod CIDR 相同的值。192.168.0.0/16
  4. 在 命名中, 将 的值设置为 etcd 服务器的 IP 地址和端口。
  5. ConfigMap
  6. calico-config
  7. etcd_endpoints
  8. 提示:您可以使用逗号作为分隔符指定多个。etcd_endpoint
  9. 如果需要,自定义清单。
  10. 使用以下命令应用清单。
  11. $ kubectl apply -f calico.yaml

1.7.Metrics部署和Dashboard部署

1.Metrics部署

下载并修改名称
docker pull bitnami/metrics-server:0.5.2
docker tag bitnami/metrics-server:0.5.2 k8s.gcr.io/metrics-server/metrics-server:v0.5.2
vim components0.5.2.yaml

  1. $ cat components0.5.2.yaml
  2. apiVersion: v1
  3. kind: ServiceAccount
  4. metadata:
  5. labels:
  6. k8s-app: metrics-server
  7. name: metrics-server
  8. namespace: kube-system
  9. ---
  10. apiVersion: rbac.authorization.k8s.io/v1
  11. kind: ClusterRole
  12. metadata:
  13. labels:
  14. k8s-app: metrics-server
  15. rbac.authorization.k8s.io/aggregate-to-admin: "true"
  16. rbac.authorization.k8s.io/aggregate-to-edit: "true"
  17. rbac.authorization.k8s.io/aggregate-to-view: "true"
  18. name: system:aggregated-metrics-reader
  19. rules:
  20. - apiGroups:
  21. - metrics.k8s.io
  22. resources:
  23. - pods
  24. - nodes
  25. verbs:
  26. - get
  27. - list
  28. - watch
  29. ---
  30. apiVersion: rbac.authorization.k8s.io/v1
  31. kind: ClusterRole
  32. metadata:
  33. labels:
  34. k8s-app: metrics-server
  35. name: system:metrics-server
  36. rules:
  37. - apiGroups:
  38. - ""
  39. resources:
  40. - pods
  41. - nodes
  42. - nodes/stats
  43. - namespaces
  44. - configmaps
  45. verbs:
  46. - get
  47. - list
  48. - watch
  49. ---
  50. apiVersion: rbac.authorization.k8s.io/v1
  51. kind: RoleBinding
  52. metadata:
  53. labels:
  54. k8s-app: metrics-server
  55. name: metrics-server-auth-reader
  56. namespace: kube-system
  57. roleRef:
  58. apiGroup: rbac.authorization.k8s.io
  59. kind: Role
  60. name: extension-apiserver-authentication-reader
  61. subjects:
  62. - kind: ServiceAccount
  63. name: metrics-server
  64. namespace: kube-system
  65. ---
  66. apiVersion: rbac.authorization.k8s.io/v1
  67. kind: ClusterRoleBinding
  68. metadata:
  69. labels:
  70. k8s-app: metrics-server
  71. name: metrics-server:system:auth-delegator
  72. roleRef:
  73. apiGroup: rbac.authorization.k8s.io
  74. kind: ClusterRole
  75. name: system:auth-delegator
  76. subjects:
  77. - kind: ServiceAccount
  78. name: metrics-server
  79. namespace: kube-system
  80. ---
  81. apiVersion: rbac.authorization.k8s.io/v1
  82. kind: ClusterRoleBinding
  83. metadata:
  84. labels:
  85. k8s-app: metrics-server
  86. name: system:metrics-server
  87. roleRef:
  88. apiGroup: rbac.authorization.k8s.io
  89. kind: ClusterRole
  90. name: system:metrics-server
  91. subjects:
  92. - kind: ServiceAccount
  93. name: metrics-server
  94. namespace: kube-system
  95. ---
  96. apiVersion: v1
  97. kind: Service
  98. metadata:
  99. labels:
  100. k8s-app: metrics-server
  101. name: metrics-server
  102. namespace: kube-system
  103. spec:
  104. ports:
  105. - name: https
  106. port: 443
  107. protocol: TCP
  108. targetPort: https
  109. selector:
  110. k8s-app: metrics-server
  111. ---
  112. apiVersion: apps/v1
  113. kind: Deployment
  114. metadata:
  115. labels:
  116. k8s-app: metrics-server
  117. name: metrics-server
  118. namespace: kube-system
  119. spec:
  120. selector:
  121. matchLabels:
  122. k8s-app: metrics-server
  123. strategy:
  124. rollingUpdate:
  125. maxUnavailable: 0
  126. template:
  127. metadata:
  128. labels:
  129. k8s-app: metrics-server
  130. spec:
  131. containers:
  132. - args:
  133. - --cert-dir=/tmp
  134. - --secure-port=4443
  135. - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
  136. - --kubelet-use-node-status-port
  137. - --metric-resolution=15s
  138. - --kubelet-insecure-tls
  139. image: k8s.gcr.io/metrics-server/metrics-server:v0.5.2
  140. imagePullPolicy: IfNotPresent
  141. livenessProbe:
  142. failureThreshold: 3
  143. httpGet:
  144. path: /livez
  145. port: https
  146. scheme: HTTPS
  147. periodSeconds: 10
  148. name: metrics-server
  149. ports:
  150. - containerPort: 4443
  151. name: https
  152. protocol: TCP
  153. readinessProbe:
  154. failureThreshold: 3
  155. httpGet:
  156. path: /readyz
  157. port: https
  158. scheme: HTTPS
  159. initialDelaySeconds: 20
  160. periodSeconds: 10
  161. resources:
  162. requests:
  163. cpu: 100m
  164. memory: 200Mi
  165. securityContext:
  166. readOnlyRootFilesystem: true
  167. runAsNonRoot: true
  168. runAsUser: 1000
  169. volumeMounts:
  170. - mountPath: /tmp
  171. name: tmp-dir
  172. nodeSelector:
  173. kubernetes.io/os: linux
  174. priorityClassName: system-cluster-critical
  175. serviceAccountName: metrics-server
  176. volumes:
  177. - emptyDir: {}
  178. name: tmp-dir
  179. ---
  180. apiVersion: apiregistration.k8s.io/v1
  181. kind: APIService
  182. metadata:
  183. labels:
  184. k8s-app: metrics-server
  185. name: v1beta1.metrics.k8s.io
  186. spec:
  187. group: metrics.k8s.io
  188. groupPriorityMinimum: 100
  189. insecureSkipTLSVerify: true
  190. service:
  191. name: metrics-server
  192. namespace: kube-system
  193. version: v1beta1
  194. versionPriority: 100

**kubectl create -f **components0.5.2.yaml

1.23.5存在问题下面的方法
地址:https://github.com/kubernetes-sigs/metrics-server
将Master01节点的front-proxy-ca.crt复制到所有Node节点
**scp /etc/kubernetes/pki/front-proxy-ca.crt k8s-node01:/etc/kubernetes/pki/front-proxy-ca.crt**
**scp /etc/kubernetes/pki/front-proxy-ca.crt k8s-node(其他节点自行拷贝):/etc/kubernetes/pki/front-proxy-ca.crt**
增加证书
vim components.yaml
- —requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt # change to front-proxy-ca.crt for kubeadm
安装metrics server
**kubectl create -f **components.yaml

2.Dashboard部署

地址:https://github.com/kubernetes/dashboard
kubectl apply -f recommended.yaml
创建管理员用户vim admin.yaml

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. name: admin-user
  5. namespace: kube-system
  6. ---
  7. apiVersion: rbac.authorization.k8s.io/v1
  8. kind: ClusterRoleBinding
  9. metadata:
  10. name: admin-user
  11. annotations:
  12. rbac.authorization.kubernetes.io/autoupdate: "true"
  13. roleRef:
  14. apiGroup: rbac.authorization.k8s.io
  15. kind: ClusterRole
  16. name: cluster-admin
  17. subjects:
  18. - kind: ServiceAccount
  19. name: admin-user
  20. namespace: kube-system

kubectl apply -f admin.yaml -n kube-system
启动错误:

  1. Events:
  2. Type Reason Age From Message
  3. ---- ------ ---- ---- -------
  4. Normal Scheduled 4m52s default-scheduler Successfully assigned kube-system/metrics-server-d9c898cdf-kpc5k to k8s-node03
  5. Normal SandboxChanged 4m32s (x2 over 4m34s) kubelet Pod sandbox changed, it will be killed and re-created.
  6. Normal Pulling 3m34s (x3 over 4m49s) kubelet Pulling image "k8s.gcr.io/metrics-server/metrics-server:v0.5.2"
  7. Warning Failed 3m19s (x3 over 4m34s) kubelet Failed to pull image "k8s.gcr.io/metrics-server/metrics-server:v0.5.2": rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
  8. Warning Failed 3m19s (x3 over 4m34s) kubelet Error: ErrImagePull
  9. Normal BackOff 2m56s (x7 over 4m32s) kubelet Back-off pulling image "k8s.gcr.io/metrics-server/metrics-server:v0.5.2"
  10. Warning Failed 2m56s (x7 over 4m32s) kubelet Error: ImagePullBackOff

解决方法:
需要手动下载镜像再进行改名(每个节点都需要下载)
镜像地址:bitnami/metrics-server - Docker Image | Docker Hub

  1. docker pull bitnami/metrics-server:0.6.1
  2. docker tag bitnami/metrics-server:0.6.1 k8s.gcr.io/metrics-server/metrics-server:v0.6.1

3.登录dashboard

更改dashboard的svc为NodePort:
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
将ClusterIP更改为NodePort(如果已经为NodePort忽略此步骤):
查看端口号:
kubectl get svc kubernetes-dashboard -n kubernetes-dashboard
根据自己的实例端口号,通过任意安装了kube-proxy的宿主机的IP+端口即可访问到dashboard:
访问Dashboard:https://10.103.236.201:18282(请更改18282为自己的端口),选择登录方式为令牌(即token方式)
查看token值:
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

4.一些必须的配置更改

将Kube-proxy改为ipvs模式,因为在初始化集群的时候注释了ipvs配置,所以需要自行修改一下:
在master01节点执行
kubectl edit cm kube-proxy -n kube-system
mode: ipvs

更新Kube-Proxy的Pod:
kubectl patch daemonset kube-proxy -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"date +’%s’\"}}}}}" -n kube-system
验证Kube-Proxy模式
curl 127.0.0.1:10249/proxyMode

1.8dashboard其它选择

Kuboard - Kubernetes 多集群管理界面
地址:https://kuboard.cn/

卸载

  • 执行 Kuboard v3 的卸载

kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3.yaml

在 master 节点以及带有 k8s.kuboard.cn/role=etcd 标签的节点上执行
rm -rf /usr/share/kuboard

2.二进制高可用安装k8s集群(生产级)

2.1高可用基本配置

1.修改apt源

所有节点配置
vim /etc/apt/sources.list

  1. deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
  2. deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
  3. deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
  4. deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
  5. deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
  6. deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
  7. deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
  8. deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
  9. deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
  10. deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse

ubuntu镜像-ubuntu下载地址-ubuntu安装教程-阿里巴巴开源镜像站 (aliyun.com)

2.修改hosts文件

所有节点配置
vim /etc/hosts

  1. 192.168.68.50 k8s-master01
  2. 192.168.68.51 k8s-master02
  3. 192.168.68.52 k8s-master03
  4. 192.168.68.48 k8s-master-lb # 如果不是高可用集群,该IP为Master01的IP
  5. 192.168.68.53 k8s-node01
  6. 192.168.68.54 k8s-node02

3.关闭swap分区

所有节点配置
vim /etc/fstab

  1. 临时禁用:swapoff -a
  2. 永久禁用:
  3. vim /etc/fstab 注释掉swap条目,重启系统

4.时间同步

所有节点

  1. apt install ntpdate -y
  2. rm -rf /etc/localtime
  3. ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  4. ntpdate cn.ntp.org.cn
  5. # 加入到crontab -e 3
  6. */5 * * * * /usr/sbin/ntpdate time2.aliyun.com
  7. # 加入到开机自动同步,vim /etc/rc.local
  8. ntpdate cn.ntp.org.cn

5.配置limit

所有节点
ulimit -SHn 65535
vim /etc/security/limits.conf
# 末尾添加如下内容

  1. * soft nofile 655360
  2. * hard nofile 131072
  3. * soft nproc 655350
  4. * hard nproc 655350
  5. * soft memlock unlimited
  6. * hard memlock unlimited

6.修改内核参数

  1. cat >/etc/sysctl.conf <<EOF
  2. # Controls source route verification
  3. net.ipv4.conf.default.rp_filter = 1
  4. net.ipv4.ip_nonlocal_bind = 1
  5. net.ipv4.ip_forward = 1
  6. # Do not accept source routing
  7. net.ipv4.conf.default.accept_source_route = 0
  8. # Controls the System Request debugging functionality of the kernel
  9. kernel.sysrq = 0
  10. # Controls whether core dumps will append the PID to the core filename.
  11. # Useful for debugging multi-threaded
  12. applications. kernel.core_uses_pid = 1
  13. # Controls the use of TCP syncookies
  14. net.ipv4.tcp_syncookies = 1
  15. # Disable netfilter on bridges.
  16. net.bridge.bridge-nf-call-ip6tables = 0
  17. net.bridge.bridge-nf-call-iptables = 0
  18. net.bridge.bridge-nf-call-arptables = 0
  19. # Controls the default maxmimum size of a mesage queue
  20. kernel.msgmnb = 65536
  21. # # Controls the maximum size of a message, in bytes
  22. kernel.msgmax = 65536
  23. # Controls the maximum shared segment size, in bytes
  24. kernel.shmmax = 68719476736
  25. # # Controls the maximum number of shared memory segments, in pages
  26. kernel.shmall = 4294967296
  27. # TCP kernel paramater
  28. net.ipv4.tcp_mem = 786432 1048576 1572864
  29. net.ipv4.tcp_rmem = 4096 87380 4194304
  30. net.ipv4.tcp_wmem = 4096 16384 4194304 n
  31. et.ipv4.tcp_window_scaling = 1
  32. net.ipv4.tcp_sack = 1
  33. # socket buffer
  34. net.core.wmem_default = 8388608
  35. net.core.rmem_default = 8388608
  36. net.core.rmem_max = 16777216
  37. net.core.wmem_max = 16777216
  38. net.core.netdev_max_backlog = 262144
  39. net.core.somaxconn = 20480
  40. net.core.optmem_max = 81920
  41. # TCP conn
  42. net.ipv4.tcp_max_syn_backlog = 262144
  43. net.ipv4.tcp_syn_retries = 3
  44. net.ipv4.tcp_retries1 = 3
  45. net.ipv4.tcp_retries2 = 15
  46. # tcp conn reuse
  47. net.ipv4.tcp_timestamps = 0
  48. net.ipv4.tcp_tw_reuse = 0
  49. net.ipv4.tcp_tw_recycle = 0
  50. net.ipv4.tcp_fin_timeout = 1
  51. net.ipv4.tcp_max_tw_buckets = 20000
  52. net.ipv4.tcp_max_orphans = 3276800
  53. net.ipv4.tcp_synack_retries = 1
  54. net.ipv4.tcp_syncookies = 1
  55. # keepalive conn
  56. net.ipv4.tcp_keepalive_time = 300
  57. net.ipv4.tcp_keepalive_intvl = 30
  58. net.ipv4.tcp_keepalive_probes = 3
  59. net.ipv4.ip_local_port_range = 10001 65000
  60. # swap
  61. vm.overcommit_memory = 0
  62. vm.swappiness = 10
  63. #net.ipv4.conf.eth1.rp_filter = 0
  64. #net.ipv4.conf.lo.arp_ignore = 1
  65. #net.ipv4.conf.lo.arp_announce = 2
  66. #net.ipv4.conf.all.arp_ignore = 1
  67. #net.ipv4.conf.all.arp_announce = 2
  68. EOF

安装常用软件
apt install wget jq psmisc vim net-tools telnet lvm2 git -y
所有节点安装ipvsadm

  1. apt install ipvsadm ipset conntrack -y
  2. modprobe -- ip_vs
  3. modprobe -- ip_vs_rr
  4. modprobe -- ip_vs_wrr
  5. modprobe -- ip_vs_sh
  6. modprobe -- nf_conntrack
  7. vim /etc/modules-load.d/ipvs.conf
  8. # 加入以下内容
  9. ip_vs
  10. ip_vs_lc
  11. ip_vs_wlc
  12. ip_vs_rr
  13. ip_vs_wrr
  14. ip_vs_lblc
  15. ip_vs_lblcr
  16. ip_vs_dh
  17. ip_vs_sh
  18. ip_vs_fo
  19. ip_vs_nq
  20. ip_vs_sed
  21. ip_vs_ftp
  22. ip_vs_sh
  23. nf_conntrack
  24. ip_tables
  25. ip_set
  26. xt_set
  27. ipt_set
  28. ipt_rpfilter
  29. ipt_REJECT
  30. ipip

然后执行systemctl enable —now systemd-modules-load.service即可
开启一些k8s集群中必须的内核参数,所有节点配置k8s内核

  1. cat <<EOF > /etc/sysctl.d/k8s.conf
  2. net.ipv4.ip_forward = 1
  3. net.bridge.bridge-nf-call-iptables = 1
  4. net.bridge.bridge-nf-call-ip6tables = 1
  5. fs.may_detach_mounts = 1
  6. net.ipv4.conf.all.route_localnet = 1
  7. vm.overcommit_memory=1
  8. vm.panic_on_oom=0
  9. fs.inotify.max_user_watches=89100
  10. fs.file-max=52706963
  11. fs.nr_open=52706963
  12. net.netfilter.nf_conntrack_max=2310720
  13. net.ipv4.tcp_keepalive_time = 600
  14. net.ipv4.tcp_keepalive_probes = 3
  15. net.ipv4.tcp_keepalive_intvl =15
  16. net.ipv4.tcp_max_tw_buckets = 36000
  17. net.ipv4.tcp_tw_reuse = 1
  18. net.ipv4.tcp_max_orphans = 327680
  19. net.ipv4.tcp_orphan_retries = 3
  20. net.ipv4.tcp_syncookies = 1
  21. net.ipv4.tcp_max_syn_backlog = 16384
  22. net.ipv4.ip_conntrack_max = 65536
  23. net.ipv4.tcp_max_syn_backlog = 16384
  24. net.ipv4.tcp_timestamps = 0
  25. net.core.somaxconn = 16384
  26. EOF

sysctl —system
所有节点配置完内核后,重启服务器,保证重启后内核依旧加载
reboot
查看
lsmod | grep —color=auto -e ip_vs -e nf_conntrack

8.Master01节点免密钥登录其他节点

安装过程中生成配置文件和证书均在Master01上操作,集群管理也在Master01上操作,阿里云或者AWS上需要单独一台kubectl服务器。密钥配置如下:
ssh-keygen -t rsa -f /root/.ssh/id_rsa -C "192.168.68.10@k8s-master01" -N ""
for i in k8s-master01 k8s-master02 k8s-node01 k8s-node02 ;do ssh-copy-id -i /root/.ssh/id_rsa.pub $i;done

9.下载安装文件

cd /root/ ; git clone [https://github.com/dotbalo/k8s-ha-install.git](https://github.com/dotbalo/k8s-ha-install.git)

2.2基本组件安装

1.所有节点安装docker

docker20.10版本K8S不支持需要安装19.03
将官方 Docker 版本库的 GPG 密钥添加到系统中:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
将 Docker 版本库添加到APT源:
add-apt-repository “deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable”
我们用新添加的 Docker 软件包来进行升级更新。
apt update
确保要从 Docker 版本库,而不是默认的 Ubuntu 版本库进行安装:
apt-cache policy docker-ce
安装 Docker :
apt install docker-ce=5:19.03.15~3-0~ubuntu-focal docker-ce-cli=5:19.03.15~3-0~ubuntu-focal -y
启动docker
systemctl status docker

提示:
由于新版kubelet建议使用systemd,所以可以把docker的CgroupDriver改成systemd
registry-mirros配置镜像加速

  1. mkdir /etc/docker
  2. cat > /etc/docker/daemon.json <<EOF
  3. {
  4. "exec-opts": ["native.cgroupdriver=systemd"],
  5. "registry-mirrors": ["https://zksmnpbq.mirror.aliyuncs.com"]
  6. }
  7. EOF

设置开机自启
**systemctl daemon-reload && systemctl enable --now docker**

2.k8s及etcd安装

以下在master01上执行

1.下载kubernetes安装包

wget [https://dl.k8s.io/v1.23.5/kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.23.5/kubernetes-server-linux-amd64.tar.gz)

2.下载etcd安装包

wget https://github.com/etcd-io/etcd/releases/download/v3.5.2/etcd-v3.5.2-linux-amd64.tar.gz

3.解压kubernetes安装文件

**tar -xf kubernetes-server-linux-amd64.tar.gz --strip-components=3 -C /usr/local/bin kubernetes/server/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy}**

4.解压etcd安装文件

**tar -zxvf etcd-v3.5.2-linux-amd64.tar.gz --strip-components=1 -C /usr/local/bin etcd-v3.5.2-linux-amd64/etcd{,ctl}**

5.版本查看

kubelet --version
etcdctl version
6.将组件发送到其他节点

  1. for NODE in k8s-master02 k8s-master03; do echo $NODE; scp /usr/local/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy} $NODE:/usr/local/bin/; scp /usr/local/bin/etcd* $NODE:/usr/local/bin/; done
  2. for NODE in k8s-node01 k8s-node02; do scp /usr/local/bin/kube{let,-proxy} $NODE:/usr/local/bin/ ; done

所有节点创建/opt/cni/bin目录

mkdir -p /opt/cni/bin

切换分支
Master01切换到1.23.x分支(其他版本可以切换到其他分支)
cd k8s-ha-install && git checkout manual-installation-v1.23.x

2.3生成证书

二进制安装最关键步骤,一步错误全盘皆输,一定要注意每个步骤都要是正确的

1.Master01下载生成证书工具

wget “https://pkg.cfssl.org/R1.2/cfssl_linux-amd64“ -O /usr/local/bin/cfssl
wget “https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64“ -O /usr/local/bin/cfssljson
chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson

2.etcd证书

所有Master节点创建etcd证书目录
mkdir /etc/etcd/ssl -p
所有节点创建kubernetes相关目录
mkdir -p /etc/kubernetes/pki
Master01节点生成etcd证书
生成证书的CSR文件:证书签名请求文件,配置了一些域名、公司、单位
cd /root/k8s-ha-install/pki

# 生成etcd CA证书和CA证书的key
cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare /etc/etcd/ssl/etcd-ca

  1. cfssl gencert \
  2. -ca=/etc/etcd/ssl/etcd-ca.pem \
  3. -ca-key=/etc/etcd/ssl/etcd-ca-key.pem \
  4. -config=ca-config.json \
  5. -hostname=127.0.0.1,k8s-master01,k8s-master02,k8s-master03,192.168.68.50,192.168.68.51,192.168.68.52 \
  6. -profile=kubernetes \
  7. etcd-csr.json | cfssljson -bare /etc/etcd/ssl/etcd
  8. 执行结果
  9. 2022/04/08 07:09:20 [INFO] generate received request
  10. 2022/04/08 07:09:20 [INFO] received CSR
  11. 2022/04/08 07:09:20 [INFO] generating key: rsa-2048
  12. 2022/04/08 07:09:21 [INFO] encoded CSR
  13. 2022/04/08 07:09:21 [INFO] signed certificate with serial number 728982787326070968690424877239840705408470785677

将证书复制到其他节点
MasterNodes=’k8s-master02 k8s-master03’

for NODE in k8s-master02 k8s-master03; do
ssh $NODE “mkdir -p /etc/etcd/ssl”
for FILE in etcd-ca-key.pem etcd-ca.pem etcd-key.pem etcd.pem; do
scp /etc/etcd/ssl/${FILE} $NODE:/etc/etcd/ssl/${FILE}
done
done

3.k8s组件证书

Master01生成kubernetes证书

cd /root/k8s-ha-install/pki

cfssl gencert -initca ca-csr.json | cfssljson -bare /etc/kubernetes/pki/ca

10.96.0.是k8s service的网段,如果说需要更改k8s service网段,那就需要更改10.96.0.1,
# 如果不是高可用集群,192.168.68.48为Master01的IP

cfssl gencert -ca=/etc/kubernetes/pki/ca.pem -ca-key=/etc/kubernetes/pki/ca-key.pem -config=ca-config.json -hostname=10.96.0.1,192.168.68.48,127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.default.svc.cluster.local,192.168.68.50,192.168.68.51,192.168.68.52 -profile=kubernetes apiserver-csr.json | cfssljson -bare /etc/kubernetes/pki/apiserver

生成apiserver的聚合证书。Requestheader-client-xxx requestheader-allowwd-xxx:aggerator
cfssl gencert -initca front-proxy-ca-csr.json | cfssljson -bare /etc/kubernetes/pki/front-proxy-ca

cfssl gencert -ca=/etc/kubernetes/pki/front-proxy-ca.pem -ca-key=/etc/kubernetes/pki/front-proxy-ca-key.pem -config=ca-config.json -profile=kubernetes front-proxy-client-csr.json | cfssljson -bare /etc/kubernetes/pki/front-proxy-client

返回结果(忽略警告)
2022/04/08 07:26:57 [INFO] generate received request
2022/04/08 07:26:57 [INFO] received CSR
2022/04/08 07:26:57 [INFO] generating key: rsa-2048
2022/04/08 07:26:58 [INFO] encoded CSR
2022/04/08 07:26:58 [INFO] signed certificate with serial number 429580583316239045765562931851686133793149712576
2022/04/08 07:26:58 [WARNING] This certificate lacks a “hosts” field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 (“Information Requirements”).

生成controller-manage的证书
cfssl gencert \
-ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
manager-csr.json | cfssljson -bare /etc/kubernetes/pki/controller-manager

# 注意,如果不是高可用集群,192.168.68.48:8443改为master01的地址,8443改为apiserver的端口,默认是6443
# set-cluster:设置一个集群项,

kubectl config set-cluster kubernetes \
—certificate-authority=/etc/kubernetes/pki/ca.pem \
—embed-certs=true \
—server=https://192.168.68.48:8443 \
—kubeconfig=/etc/kubernetes/controller-manager.kubeconfig

# set-credentials 设置一个用户项
kubectl config set-credentials system:kube-controller-manager \
—client-certificate=/etc/kubernetes/pki/controller-manager.pem \
—client-key=/etc/kubernetes/pki/controller-manager-key.pem \
—embed-certs=true \
—kubeconfig=/etc/kubernetes/controller-manager.kubeconfig

# 设置一个环境项,一个上下文
kubectl config set-context system:kube-controller-manager@kubernetes \
—cluster=kubernetes \
—user=system:kube-controller-manager \
—kubeconfig=/etc/kubernetes/controller-manager.kubeconfig

# 使用某个环境当做默认环境
kubectl config use-context system:kube-controller-manager@kubernetes \
—kubeconfig=/etc/kubernetes/controller-manager.kubeconfig

cfssl gencert \
-ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
scheduler-csr.json | cfssljson -bare /etc/kubernetes/pki/scheduler

# 注意,如果不是高可用集群,192.168.68.48:8443改为master01的地址,8443改为apiserver的端口,默认是6443

kubectl config set-cluster kubernetes \
—certificate-authority=/etc/kubernetes/pki/ca.pem \
—embed-certs=true \
—server=https://192.168.68.48:8443 \
—kubeconfig=/etc/kubernetes/scheduler.kubeconfig

kubectl config set-credentials system:kube-scheduler \
—client-certificate=/etc/kubernetes/pki/scheduler.pem \
—client-key=/etc/kubernetes/pki/scheduler-key.pem \
—embed-certs=true \
—kubeconfig=/etc/kubernetes/scheduler.kubeconfig

kubectl config set-context system:kube-scheduler@kubernetes \
—cluster=kubernetes \
—user=system:kube-scheduler \
—kubeconfig=/etc/kubernetes/scheduler.kubeconfig

kubectl config use-context system:kube-scheduler@kubernetes \
—kubeconfig=/etc/kubernetes/scheduler.kubeconfig

cfssl gencert \
-ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
admin-csr.json | cfssljson -bare /etc/kubernetes/pki/admin

# 注意,如果不是高可用集群,192.168.68.48:8443改为master01的地址,8443改为apiserver的端口,默认是6443

kubectl config set-cluster kubernetes —certificate-authority=/etc/kubernetes/pki/ca.pem —embed-certs=true —server=https://192.168.68.48:8443 —kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config set-credentials kubernetes-admin —client-certificate=/etc/kubernetes/pki/admin.pem —client-key=/etc/kubernetes/pki/admin-key.pem —embed-certs=true —kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config set-context kubernetes-admin@kubernetes —cluster=kubernetes —user=kubernetes-admin —kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config use-context kubernetes-admin@kubernetes —kubeconfig=/etc/kubernetes/admin.kubeconfig

创建ServiceAccount Key à secret
openssl genrsa -out /etc/kubernetes/pki/sa.key 2048

返回结果
Generating RSA private key, 2048 bit long modulus (2 primes)
……………………………+++++
……………………………………………………………………………………………..+++++
e is 65537 (0x010001)

openssl rsa -in /etc/kubernetes/pki/sa.key -pubout -out /etc/kubernetes/pki/sa.pub

发送证书至其他节点
for NODE in k8s-master02 k8s-master03; do for FILE in $(ls /etc/kubernetes/pki | grep -v etcd); do scp /etc/kubernetes/pki/${FILE} $NODE:/etc/kubernetes/pki/${FILE};done; for FILE in admin.kubeconfig controller-manager.kubeconfig scheduler.kubeconfig; do scp /etc/kubernetes/${FILE} $NODE:/etc/kubernetes/${FILE};done;done**

查看证书文件
[root@k8s-master01 pki]# ls /etc/kubernetes/pki/
admin.csr apiserver.csr ca.csr controller-manager.csr front-proxy-ca.csr front-proxy-client.csr sa.key scheduler-key.pem
admin-key.pem apiserver-key.pem ca-key.pem controller-manager-key.pem front-proxy-ca-key.pem front-proxy-client-key.pem sa.pub scheduler.pem
admin.pem apiserver.pem ca.pem controller-manager.pem front-proxy-ca.pem front-proxy-client.pem scheduler.csr
[root@k8s-master01 pki]# ls /etc/kubernetes/pki/ |wc -l
23

2.4高可用及etcd配置

1.etcd配置

etcd配置大致相同,注意修改每个Master节点的etcd配置的主机名和IP地址

Master01

vim /etc/etcd/etcd.config.yml

  1. name: 'k8s-master01'
  2. data-dir: /var/lib/etcd
  3. wal-dir: /var/lib/etcd/wal
  4. snapshot-count: 5000
  5. heartbeat-interval: 100
  6. election-timeout: 1000
  7. quota-backend-bytes: 0
  8. listen-peer-urls: 'https://192.168.68.50:2380'
  9. listen-client-urls: 'https://192.168.68.50:2379,http://127.0.0.1:2379'
  10. max-snapshots: 3
  11. max-wals: 5
  12. cors:
  13. initial-advertise-peer-urls: 'https://192.168.68.50:2380'
  14. advertise-client-urls: 'https://192.168.68.50:2379'
  15. discovery:
  16. discovery-fallback: 'proxy'
  17. discovery-proxy:
  18. discovery-srv:
  19. initial-cluster: 'k8s-master01=https://192.168.68.50:2380,k8s-master02=https://192.168.68.51:2380,k8s-master03=https://192.168.68.52:2380'
  20. initial-cluster-token: 'etcd-k8s-cluster'
  21. initial-cluster-state: 'new'
  22. strict-reconfig-check: false
  23. enable-v2: true
  24. enable-pprof: true
  25. proxy: 'off'
  26. proxy-failure-wait: 5000
  27. proxy-refresh-interval: 30000
  28. proxy-dial-timeout: 1000
  29. proxy-write-timeout: 5000
  30. proxy-read-timeout: 0
  31. client-transport-security:
  32. cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  33. key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  34. client-cert-auth: true
  35. trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  36. auto-tls: true
  37. peer-transport-security:
  38. cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  39. key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  40. peer-client-cert-auth: true
  41. trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  42. auto-tls: true
  43. debug: false
  44. log-package-levels:
  45. log-outputs: [default]
  46. force-new-cluster: false

Master02

vim /etc/etcd/etcd.config.yml

  1. name: 'k8s-master02'
  2. data-dir: /var/lib/etcd
  3. wal-dir: /var/lib/etcd/wal
  4. snapshot-count: 5000
  5. heartbeat-interval: 100
  6. election-timeout: 1000
  7. quota-backend-bytes: 0
  8. listen-peer-urls: 'https://192.168.68.51:2380'
  9. listen-client-urls: 'https://192.168.68.51:2379,http://127.0.0.1:2379'
  10. max-snapshots: 3
  11. max-wals: 5
  12. cors:
  13. initial-advertise-peer-urls: 'https://192.168.68.51:2380'
  14. advertise-client-urls: 'https://192.168.68.51:2379'
  15. discovery:
  16. discovery-fallback: 'proxy'
  17. discovery-proxy:
  18. discovery-srv:
  19. initial-cluster: 'k8s-master01=https://192.168.68.50:2380,k8s-master02=https://192.168.68.51:2380,k8s-master03=https://192.168.68.52:2380'
  20. initial-cluster-token: 'etcd-k8s-cluster'
  21. initial-cluster-state: 'new'
  22. strict-reconfig-check: false
  23. enable-v2: true
  24. enable-pprof: true
  25. proxy: 'off'
  26. proxy-failure-wait: 5000
  27. proxy-refresh-interval: 30000
  28. proxy-dial-timeout: 1000
  29. proxy-write-timeout: 5000
  30. proxy-read-timeout: 0
  31. client-transport-security:
  32. cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  33. key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  34. client-cert-auth: true
  35. trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  36. auto-tls: true
  37. peer-transport-security:
  38. cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  39. key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  40. peer-client-cert-auth: true
  41. trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  42. auto-tls: true
  43. debug: false
  44. log-package-levels:
  45. log-outputs: [default]
  46. force-new-cluster: false

Master03

vim /etc/etcd/etcd.config.yml

  1. name: 'k8s-master03'
  2. data-dir: /var/lib/etcd
  3. wal-dir: /var/lib/etcd/wal
  4. snapshot-count: 5000
  5. heartbeat-interval: 100
  6. election-timeout: 1000
  7. quota-backend-bytes: 0
  8. listen-peer-urls: 'https://192.168.68.52:2380'
  9. listen-client-urls: 'https://192.168.68.52:2379,http://127.0.0.1:2379'
  10. max-snapshots: 3
  11. max-wals: 5
  12. cors:
  13. initial-advertise-peer-urls: 'https://192.168.68.52:2380'
  14. advertise-client-urls: 'https://192.168.68.52:2379'
  15. discovery:
  16. discovery-fallback: 'proxy'
  17. discovery-proxy:
  18. discovery-srv:
  19. initial-cluster: 'k8s-master01=https://192.168.68.50:2380,k8s-master02=https://192.168.68.51:2380,k8s-master03=https://192.168.68.52:2380'
  20. initial-cluster-token: 'etcd-k8s-cluster'
  21. initial-cluster-state: 'new'
  22. strict-reconfig-check: false
  23. enable-v2: true
  24. enable-pprof: true
  25. proxy: 'off'
  26. proxy-failure-wait: 5000
  27. proxy-refresh-interval: 30000
  28. proxy-dial-timeout: 1000
  29. proxy-write-timeout: 5000
  30. proxy-read-timeout: 0
  31. client-transport-security:
  32. cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  33. key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  34. client-cert-auth: true
  35. trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  36. auto-tls: true
  37. peer-transport-security:
  38. cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
  39. key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
  40. peer-client-cert-auth: true
  41. trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
  42. auto-tls: true
  43. debug: false
  44. log-package-levels:
  45. log-outputs: [default]
  46. force-new-cluster: false

创建Service

所有Master节点创建etcd service并启动
vim /usr/lib/systemd/system/etcd.service

  1. [Unit]
  2. Description=Etcd Service
  3. Documentation=https://coreos.com/etcd/docs/latest/
  4. After=network.target
  5. [Service]
  6. Type=notify
  7. ExecStart=/usr/local/bin/etcd --config-file=/etc/etcd/etcd.config.yml
  8. Restart=on-failure
  9. RestartSec=10
  10. LimitNOFILE=65536
  11. [Install]
  12. WantedBy=multi-user.target
  13. Alias=etcd3.service

所有Master节点创建etcd的证书目录
mkdir /etc/kubernetes/pki/etcd
ln -s /etc/etcd/ssl/* /etc/kubernetes/pki/etcd/
systemctl daemon-reload
systemctl enable —now etcd

启动异常
Job for etcd.service failed because the control process exited with error code.
See “systemctl status etcd.service” and “journalctl -xe” for details.

  1. ~ # journalctl -xe 1 ↵ root@k8s-master02
  2. Apr 09 08:24:08 k8s-master02 multipathd[707]: sda: failed to get sysfs uid: Invalid argument
  3. Apr 09 08:24:08 k8s-master02 multipathd[707]: sda: failed to get sgio uid: No such file or directory
  4. Apr 09 08:24:12 k8s-master02 systemd[1]: etcd.service: Scheduled restart job, restart counter is at 3989.
  5. -- Subject: Automatic restarting of a unit has been scheduled
  6. -- Defined-By: systemd
  7. -- Support: http://www.ubuntu.com/support
  8. --
  9. -- Automatic restarting of the unit etcd.service has been scheduled, as the result for
  10. -- the configured Restart= setting for the unit.
  11. Apr 09 08:24:12 k8s-master02 systemd[1]: Stopped Etcd Service.
  12. -- Subject: A stop job for unit etcd.service has finished
  13. -- Defined-By: systemd
  14. -- Support: http://www.ubuntu.com/support
  15. --
  16. -- A stop job for unit etcd.service has finished.
  17. --
  18. -- The job identifier is 308572 and the job result is done.
  19. Apr 09 08:24:12 k8s-master02 systemd[1]: Starting Etcd Service...
  20. -- Subject: A start job for unit etcd.service has begun execution
  21. -- Defined-By: systemd
  22. -- Support: http://www.ubuntu.com/support
  23. --
  24. -- A start job for unit etcd.service has begun execution.
  25. --
  26. -- The job identifier is 308572.
  27. Apr 09 08:24:12 k8s-master02 etcd[109903]: {"level":"info","ts":"2022-04-09T08:24:12.320+0800","caller":"etcdmain/config.go:339","msg":"loaded server configuration, other configuration command line flags a>
  28. Apr 09 08:24:12 k8s-master02 etcd[109903]: {"level":"info","ts":"2022-04-09T08:24:12.321+0800","caller":"etcdmain/etcd.go:72","msg":"Running: ","args":["/usr/local/bin/etcd","--config-file=/etc/etcd/etcd.c>
  29. Apr 09 08:24:12 k8s-master02 etcd[109903]: {"level":"info","ts":"2022-04-09T08:24:12.321+0800","caller":"embed/etcd.go:131","msg":"configuring peer listeners","listen-peer-urls":["https://192.168.68.51:238>
  30. Apr 09 08:24:12 k8s-master02 etcd[109903]: {"level":"info","ts":"2022-04-09T08:24:12.321+0800","caller":"embed/etcd.go:368","msg":"closing etcd server","name":"k8s-master02","data-dir":"/var/lib/etcd","adv>
  31. Apr 09 08:24:12 k8s-master02 etcd[109903]: {"level":"info","ts":"2022-04-09T08:24:12.321+0800","caller":"embed/etcd.go:370","msg":"closed etcd server","name":"k8s-master02","data-dir":"/var/lib/etcd","adve>
  32. Apr 09 08:24:12 k8s-master02 etcd[109903]: {"level":"warn","ts":"2022-04-09T08:24:12.321+0800","caller":"etcdmain/etcd.go:145","msg":"failed to start etcd","error":"cannot listen on TLS for 192.168.68.51:2>
  33. Apr 09 08:24:12 k8s-master02 etcd[109903]: {"level":"fatal","ts":"2022-04-09T08:24:12.321+0800","caller":"etcdmain/etcd.go:203","msg":"discovery failed","error":"cannot listen on TLS for 192.168.68.51:2380>
  34. Apr 09 08:24:12 k8s-master02 systemd[1]: etcd.service: Main process exited, code=exited, status=1/FAILURE
  35. -- Subject: Unit process exited
  36. -- Defined-By: systemd
  37. -- Support: http://www.ubuntu.com/support
  38. --
  39. -- An ExecStart= process belonging to unit etcd.service has exited.
  40. --
  41. -- The process' exit code is 'exited' and its exit status is 1.
  42. Apr 09 08:24:12 k8s-master02 systemd[1]: etcd.service: Failed with result 'exit-code'.
  43. -- Subject: Unit failed
  44. -- Defined-By: systemd
  45. -- Support: http://www.ubuntu.com/support
  46. --
  47. -- The unit etcd.service has entered the 'failed' state with result 'exit-code'.
  48. Apr 09 08:24:12 k8s-master02 systemd[1]: Failed to start Etcd Service.
  49. -- Subject: A start job for unit etcd.service has failed
  50. -- Defined-By: systemd
  51. -- Support: http://www.ubuntu.com/support
  52. --
  53. -- A start job for unit etcd.service has finished with a failure.
  54. --
  55. -- The job identifier is 308572 and the job result is failed.
  56. Apr 09 08:24:13 k8s-master02 multipathd[707]: sda: add missing path
  57. Apr 09 08:24:13 k8s-master02 multipathd[707]: sda: failed to get udev uid: Invalid argument
  58. Apr 09 08:24:13 k8s-master02 multipathd[707]: sda: failed to get sysfs uid: Invalid argument
  59. Apr 09 08:24:13 k8s-master02 multipathd[707]: sda: failed to get sgio uid: No such file or directory

1.修改/etc/multipath.conf文件

sudo vi /etc/multipath.conf
2.添加以下内容,sda视本地环境做调整

blacklist {
devnode “^sda”
}
3.重启multipath-tools服务

sudo service multipath-tools restart

[

](https://blog.csdn.net/zhangchenbin/article/details/117886448)

查看etcd状态
export ETCDCTL_API=3

etcdctl —endpoints=”192.168.68.50:2379,192.168.68.51:2379,192.168.68.52:2379” —cacert=/etc/kubernetes/pki/etcd/etcd-ca.pem —cert=/etc/kubernetes/pki/etcd/etcd.pem —key=/etc/kubernetes/pki/etcd/etcd-key.pem endpoint status —write-out=table

2.高可用配置

高可用配置(注意:如果不是高可用集群,haproxy和keepalived无需安装)
如果在云上安装也无需执行此章节的步骤,可以直接使用云上的lb,比如阿里云slb,腾讯云elb等
公有云要用公有云自带的负载均衡,比如阿里云的SLB,腾讯云的ELB,用来替代haproxy和keepalived,因为公有云大部分都是不支持keepalived的,另外如果用阿里云的话,kubectl控制端不能放在master节点,推荐使用腾讯云,因为阿里云的slb有回环的问题,也就是slb代理的服务器不能反向访问SLB,但是腾讯云修复了这个问题。

Slb -> haproxy -> apiserver
所有Master节点安装keepalived和haproxy
apt install keepalived haproxy -y

所有Master配置HAProxy,配置一样

vim /etc/haproxy/haproxy.cfg

  1. global
  2. maxconn 2000
  3. ulimit-n 16384
  4. log 127.0.0.1 local0 err
  5. stats timeout 30s
  6. defaults
  7. log global
  8. mode http
  9. option httplog
  10. timeout connect 5000
  11. timeout client 50000
  12. timeout server 50000
  13. timeout http-request 15s
  14. timeout http-keep-alive 15s
  15. frontend k8s-master
  16. bind 0.0.0.0:8443
  17. bind 127.0.0.1:8443
  18. mode tcp
  19. option tcplog
  20. tcp-request inspect-delay 5s
  21. default_backend k8s-master
  22. backend k8s-master
  23. mode tcp
  24. option tcplog
  25. option tcp-check
  26. balance roundrobin
  27. default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
  28. server k8s-master01 192.168.68.50:6443 check
  29. server k8s-master02 192.168.68.51:6443 check
  30. server k8s-master03 192.168.68.52:6443 check

Master01 keepalived

所有Master节点配置KeepAlived,配置不一样,注意区分 [root@k8s-master01 pki]# vim /etc/keepalived/keepalived.conf ,注意每个节点的IP和网卡(interface参数)

  1. ! Configuration File for keepalived
  2. global_defs {
  3. router_id LVS_DEVEL
  4. }
  5. vrrp_script chk_apiserver {
  6. script "/etc/keepalived/check_apiserver.sh"
  7. interval 5
  8. weight -5
  9. fall 2
  10. rise 1
  11. }
  12. vrrp_instance VI_1 {
  13. state MASTER
  14. interface ens33
  15. mcast_src_ip 192.168.68.50
  16. virtual_router_id 51
  17. priority 101
  18. nopreempt
  19. advert_int 2
  20. authentication {
  21. auth_type PASS
  22. auth_pass K8SHA_KA_AUTH
  23. }
  24. virtual_ipaddress {
  25. 192.168.68.48
  26. }
  27. track_script {
  28. chk_apiserver
  29. } }

Master02 keepalived
  1. ! Configuration File for keepalived
  2. global_defs {
  3. router_id LVS_DEVEL
  4. }
  5. vrrp_script chk_apiserver {
  6. script "/etc/keepalived/check_apiserver.sh"
  7. interval 5
  8. weight -5
  9. fall 2
  10. rise 1
  11. }
  12. vrrp_instance VI_1 {
  13. state BACKUP
  14. interface ens33
  15. mcast_src_ip 192.168.68.51
  16. virtual_router_id 51
  17. priority 100
  18. nopreempt
  19. advert_int 2
  20. authentication {
  21. auth_type PASS
  22. auth_pass K8SHA_KA_AUTH
  23. }
  24. virtual_ipaddress {
  25. 192.168.68.48
  26. }
  27. track_script {
  28. chk_apiserver
  29. } }

Master03 keepalived
  1. ! Configuration File for keepalived
  2. global_defs {
  3. router_id LVS_DEVEL
  4. }
  5. vrrp_script chk_apiserver {
  6. script "/etc/keepalived/check_apiserver.sh"
  7. interval 5
  8. weight -5
  9. fall 2
  10. rise 1
  11. }
  12. vrrp_instance VI_1 {
  13. state BACKUP
  14. interface ens33
  15. mcast_src_ip 192.168.68.52
  16. virtual_router_id 51
  17. priority 100
  18. nopreempt
  19. advert_int 2
  20. authentication {
  21. auth_type PASS
  22. auth_pass K8SHA_KA_AUTH
  23. }
  24. virtual_ipaddress {
  25. 192.168.68.48
  26. }
  27. track_script {
  28. chk_apiserver
  29. } }

健康检查配置

所有master节点
[root@k8s-master01 keepalived]# cat /etc/keepalived/check_apiserver.sh

  1. #!/bin/bash
  2. err=0
  3. for k in $(seq 1 3)
  4. do
  5. check_code=$(pgrep haproxy)
  6. if [[ $check_code == "" ]]; then
  7. err=$(expr $err + 1)
  8. sleep 1
  9. continue
  10. else
  11. err=0
  12. break
  13. fi
  14. done
  15. if [[ $err != "0" ]]; then
  16. echo "systemctl stop keepalived"
  17. /usr/bin/systemctl stop keepalived
  18. exit 1
  19. else
  20. exit 0
  21. fi

chmod +x /etc/keepalived/check_apiserver.sh
所有master节点启动haproxy和keepalived
[root@k8s-master01 keepalived]# systemctl daemon-reload
[root@k8s-master01 keepalived]# systemctl enable —now haproxy
[root@k8s-master01 keepalived]# systemctl enable —now keepalived

VIP测试

[root@k8s-master01 pki]# ping 192.168.68.48
PING 192.168.0.236 (192.168.0.236) 56(84) bytes of data.
64 bytes from 192.168.0.236: icmp_seq=1 ttl=64 time=1.39 ms
64 bytes from 192.168.0.236: icmp_seq=2 ttl=64 time=2.46 ms
64 bytes from 192.168.0.236: icmp_seq=3 ttl=64 time=1.68 ms
64 bytes from 192.168.0.236: icmp_seq=4 ttl=64 time=1.08 ms
重要:如果安装了keepalived和haproxy,需要测试keepalived是否是正常的
telnet 192.168.68.48 8443
如果ping不通且telnet没有出现 ],则认为VIP不可以,不可在继续往下执行,需要排查keepalived的问题,比如防火墙和selinux,haproxy和keepalived的状态,监听端口等
所有节点查看防火墙状态必须为disable和inactive:systemctl status firewalld
所有节点查看selinux状态,必须为disable:getenforce
master节点查看haproxy和keepalived状态:systemctl status keepalived haproxy
master节点查看监听端口:netstat -lntp

2.5k8s组件配置

1.Apiserver

所有Master节点创建kube-apiserver service,# 注意,如果不是高可用集群,192.168.0.236改为master01的地址

Master01配置

注意本文档使用的k8s service网段为10.96.0.0/12,该网段不能和宿主机的网段、Pod网段的重复,请按需修改

[root@k8s-master01 pki]# cat /usr/lib/systemd/system/kube-apiserver.service

  1. [Unit]
  2. Description=Kubernetes API Server
  3. Documentation=https://github.com/kubernetes/kubernetes
  4. After=network.target
  5. [Service]
  6. ExecStart=/usr/local/bin/kube-apiserver \
  7. --v=2 \
  8. --logtostderr=true \
  9. --allow-privileged=true \
  10. --bind-address=0.0.0.0 \
  11. --secure-port=6443 \
  12. --insecure-port=0 \
  13. --advertise-address=192.168.68.50 \
  14. --service-cluster-ip-range=10.96.0.0/12 \
  15. --service-node-port-range=30000-32767 \
  16. --etcd-servers=https://192.168.68.50:2379,https://192.168.68.51:2379,https://192.168.68.52:2379 \
  17. --etcd-cafile=/etc/etcd/ssl/etcd-ca.pem \
  18. --etcd-certfile=/etc/etcd/ssl/etcd.pem \
  19. --etcd-keyfile=/etc/etcd/ssl/etcd-key.pem \
  20. --client-ca-file=/etc/kubernetes/pki/ca.pem \
  21. --tls-cert-file=/etc/kubernetes/pki/apiserver.pem \
  22. --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem \
  23. --kubelet-client-certificate=/etc/kubernetes/pki/apiserver.pem \
  24. --kubelet-client-key=/etc/kubernetes/pki/apiserver-key.pem \
  25. --service-account-key-file=/etc/kubernetes/pki/sa.pub \
  26. --service-account-signing-key-file=/etc/kubernetes/pki/sa.key \
  27. --service-account-issuer=https://kubernetes.default.svc.cluster.local \
  28. --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \
  29. --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota \
  30. --authorization-mode=Node,RBAC \
  31. --enable-bootstrap-token-auth=true \
  32. --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem \
  33. --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.pem \
  34. --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client-key.pem \
  35. --requestheader-allowed-names=aggregator \
  36. --requestheader-group-headers=X-Remote-Group \
  37. --requestheader-extra-headers-prefix=X-Remote-Extra- \
  38. --requestheader-username-headers=X-Remote-User
  39. # --token-auth-file=/etc/kubernetes/token.csv
  40. Restart=on-failure
  41. RestartSec=10s
  42. LimitNOFILE=65535
  43. [Install]
  44. WantedBy=multi-user.target

Master02配置

注意本文档使用的k8s service网段为10.96.0.0/12,该网段不能和宿主机的网段、Pod网段的重复,请按需修改
[root@k8s-master01 pki]# cat /usr/lib/systemd/system/kube-apiserver.service

  1. [Unit]
  2. Description=Kubernetes API Server
  3. Documentation=https://github.com/kubernetes/kubernetes
  4. After=network.target
  5. [Service]
  6. ExecStart=/usr/local/bin/kube-apiserver \
  7. --v=2 \
  8. --logtostderr=true \
  9. --allow-privileged=true \
  10. --bind-address=0.0.0.0 \
  11. --secure-port=6443 \
  12. --insecure-port=0 \
  13. --advertise-address=192.168.68.51 \
  14. --service-cluster-ip-range=10.96.0.0/12 \
  15. --service-node-port-range=30000-32767 \
  16. --etcd-servers=https://192.168.68.50:2379,https://192.168.68.51:2379,https://192.168.68.52:2379 \
  17. --etcd-cafile=/etc/etcd/ssl/etcd-ca.pem \
  18. --etcd-certfile=/etc/etcd/ssl/etcd.pem \
  19. --etcd-keyfile=/etc/etcd/ssl/etcd-key.pem \
  20. --client-ca-file=/etc/kubernetes/pki/ca.pem \
  21. --tls-cert-file=/etc/kubernetes/pki/apiserver.pem \
  22. --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem \
  23. --kubelet-client-certificate=/etc/kubernetes/pki/apiserver.pem \
  24. --kubelet-client-key=/etc/kubernetes/pki/apiserver-key.pem \
  25. --service-account-key-file=/etc/kubernetes/pki/sa.pub \
  26. --service-account-signing-key-file=/etc/kubernetes/pki/sa.key \
  27. --service-account-issuer=https://kubernetes.default.svc.cluster.local \
  28. --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \
  29. --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota \
  30. --authorization-mode=Node,RBAC \
  31. --enable-bootstrap-token-auth=true \
  32. --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem \
  33. --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.pem \
  34. --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client-key.pem \
  35. --requestheader-allowed-names=aggregator \
  36. --requestheader-group-headers=X-Remote-Group \
  37. --requestheader-extra-headers-prefix=X-Remote-Extra- \
  38. --requestheader-username-headers=X-Remote-User
  39. # --token-auth-file=/etc/kubernetes/token.csv
  40. Restart=on-failure
  41. RestartSec=10s
  42. LimitNOFILE=65535
  43. [Install]
  44. WantedBy=multi-user.target

Master03配置

注意本文档使用的k8s service网段为10.96.0.0/12,该网段不能和宿主机的网段、Pod网段的重复,请按需修改
cat /usr/lib/systemd/system/kube-apiserver.service

  1. [Unit]
  2. Description=Kubernetes API Server
  3. Documentation=https://github.com/kubernetes/kubernetes
  4. After=network.target
  5. [Service]
  6. ExecStart=/usr/local/bin/kube-apiserver \
  7. --v=2 \
  8. --logtostderr=true \
  9. --allow-privileged=true \
  10. --bind-address=0.0.0.0 \
  11. --secure-port=6443 \
  12. --insecure-port=0 \
  13. --advertise-address=192.168.68.52 \
  14. --service-cluster-ip-range=10.96.0.0/12 \
  15. --service-node-port-range=30000-32767 \
  16. --etcd-servers=https://192.168.68.50:2379,https://192.168.68.51:2379,https://192.168.68.52:2379 \
  17. --etcd-cafile=/etc/etcd/ssl/etcd-ca.pem \
  18. --etcd-certfile=/etc/etcd/ssl/etcd.pem \
  19. --etcd-keyfile=/etc/etcd/ssl/etcd-key.pem \
  20. --client-ca-file=/etc/kubernetes/pki/ca.pem \
  21. --tls-cert-file=/etc/kubernetes/pki/apiserver.pem \
  22. --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem \
  23. --kubelet-client-certificate=/etc/kubernetes/pki/apiserver.pem \
  24. --kubelet-client-key=/etc/kubernetes/pki/apiserver-key.pem \
  25. --service-account-key-file=/etc/kubernetes/pki/sa.pub \
  26. --service-account-signing-key-file=/etc/kubernetes/pki/sa.key \
  27. --service-account-issuer=https://kubernetes.default.svc.cluster.local \
  28. --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \
  29. --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota \
  30. --authorization-mode=Node,RBAC \
  31. --enable-bootstrap-token-auth=true \
  32. --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem \
  33. --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.pem \
  34. --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client-key.pem \
  35. --requestheader-allowed-names=aggregator \
  36. --requestheader-group-headers=X-Remote-Group \
  37. --requestheader-extra-headers-prefix=X-Remote-Extra- \
  38. --requestheader-username-headers=X-Remote-User
  39. # --token-auth-file=/etc/kubernetes/token.csv
  40. Restart=on-failure
  41. RestartSec=10s
  42. LimitNOFILE=65535
  43. [Install]
  44. WantedBy=multi-user.target

启动apiserver

所有Master节点开启kube-apiserver
systemctl daemon-reload && systemctl enable —now kube-apiserver
检测kube-server状态
# systemctl status kube-apiserver

● kube-apiserver.service - Kubernetes API Server
Loaded: loaded (/usr/lib/systemd/system/kube-apiserver.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2020-08-22 21:26:49 CST; 26s ago
系统日志的这些提示可以忽略
Dec 11 20:51:15 k8s-master01 kube-apiserver: I1211 20:51:15.004739 7450 clientconn.go:948] ClientConn switching balancer to “pick_first”
Dec 11 20:51:15 k8s-master01 kube-apiserver: I1211 20:51:15.004843 7450 balancer_conn_wrappers.go:78] pickfirstBalancer: HandleSubConnStateChange: 0xc011bd4c80, {CONNECTING }
Dec 11 20:51:15 k8s-master01 kube-apiserver: I1211 20:51:15.010725 7450 balancer_conn_wrappers.go:78] pickfirstBalancer: HandleSubConnStateChange: 0xc011bd4c80, {READY }
Dec 11 20:51:15 k8s-master01 kube-apiserver: I1211 20:51:15.011370 7450 controlbuf.go:508] transport: loopyWriter.run returning. connection error: desc = “transport is closing”

2. ControllerManager

所有Master节点配置kube-controller-manager service
注意本文档使用的k8s Pod网段为172.16.0.0/12,该网段不能和宿主机的网段、k8s Service网段的重复,请按需修改
[root@k8s-master01 pki]# cat /usr/lib/systemd/system/kube-controller-manager.service

  1. [Unit]
  2. Description=Kubernetes Controller Manager
  3. Documentation=https://github.com/kubernetes/kubernetes
  4. After=network.target
  5. [Service]
  6. ExecStart=/usr/local/bin/kube-controller-manager \
  7. --v=2 \
  8. --logtostderr=true \
  9. --address=127.0.0.1 \
  10. --root-ca-file=/etc/kubernetes/pki/ca.pem \
  11. --cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem \
  12. --cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem \
  13. --service-account-private-key-file=/etc/kubernetes/pki/sa.key \
  14. --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig \
  15. --leader-elect=true \
  16. --use-service-account-credentials=true \
  17. --node-monitor-grace-period=40s \
  18. --node-monitor-period=5s \
  19. --pod-eviction-timeout=2m0s \
  20. --controllers=*,bootstrapsigner,tokencleaner \
  21. --allocate-node-cidrs=true \
  22. --cluster-cidr=172.16.0.0/12 \
  23. --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem \
  24. --node-cidr-mask-size=24
  25. Restart=always
  26. RestartSec=10s
  27. [Install]
  28. WantedBy=multi-user.target

所有Master节点启动kube-controller-manager
[root@k8s-master01 pki]# systemctl daemon-reload

[root@k8s-master01 pki]# systemctl enable —now kube-controller-manager
Created symlink /etc/systemd/system/multi-user.target.wants/kube-controller-manager.service → /usr/lib/systemd/system/kube-controller-manager.service.

查看启动状态
[root@k8s-master01 pki]# systemctl enable —now kube-controller-manager
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-controller-manager.service to /usr/lib/systemd/system/kube-controller-manager.service.
[root@k8s-master01 pki]# systemctl status kube-controller-manager
● kube-controller-manager.service - Kubernetes Controller Manager
Loaded: loaded (/usr/lib/systemd/system/kube-controller-manager.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2020-12-11 20:53:05 CST; 8s ago
Docs: https://github.com/kubernetes/kubernetes
Main PID: 7518 (kube-controller)

3.Scheduler

所有Master节点配置kube-scheduler service
[root@k8s-master01 pki]# cat /usr/lib/systemd/system/kube-scheduler.service

  1. [Unit]
  2. Description=Kubernetes Scheduler
  3. Documentation=https://github.com/kubernetes/kubernetes
  4. After=network.target
  5. [Service]
  6. ExecStart=/usr/local/bin/kube-scheduler \
  7. --v=2 \
  8. --logtostderr=true \
  9. --address=127.0.0.1 \
  10. --leader-elect=true \
  11. --kubeconfig=/etc/kubernetes/scheduler.kubeconfig
  12. Restart=always
  13. RestartSec=10s
  14. [Install]
  15. WantedBy=multi-user.target

[root@k8s-master01 pki]# systemctl daemon-reload

[root@k8s-master01 pki]# systemctl enable —now kube-scheduler
Created symlink /etc/systemd/system/multi-user.target.wants/kube-scheduler.service → /usr/lib/systemd/system/kube-scheduler.service.

2.6 TLS Bootstrapping自动颁发证书

2.7 二进制Node节点及Calico配置

2.8 二进制Metrics&Dashboard安装

2.9 二进制高可用集群可用性验证

2.10 生产环境k8s集群关键性配置

2.11Bootstrapping

1.Kubelet启动过程

2.CSR申请和证书颁发原理

3.证书自动续期原理_

二、K8S基础篇

1.必备Docker知识

2.基本概念

3.资源调度

4.服务发布入门

5.配置管理

三、K8S进阶篇

1.持久化存储入门

1.1 Volumes

容器的生命周期可能很短,会被频繁地创建和销毁。那么容器在销毁时,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。Container(容器)中的磁盘文件是短暂的,当容器崩溃时,kubelet会重新启动容器,但最初的文件将丢失,Container会以最干净的状态启动。为了持久化保存容器的数据,kubernetes引入了Volume的概念。

Volume是Pod中能够被多个容器访问的共享目录,它被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下,kubernetes通过Volume实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储。Volume的生命容器不与Pod中单个容器的生命周期相关,当容器终止或者重启时,Volume中的数据也不会丢失。

一些需要持久化数据的程序才会用到Volumes,或者一些需要共享数据的容器需要volumes。
Redis-Cluster:nodes.conf
日志收集的需求:需要在应用程序的容器里面加一个sidecar,这个容器是一个收集日志的容器,比如filebeat,它通过volumes共享应用程序的日志文件目录。
Volumes:官方文档https://kubernetes.io/docs/concepts/storage/volumes/

Docker也有卷的概念,但是在Docker中卷只是磁盘上或另一个Container中的目录,其生命周期不受管理。虽然目前Docker已经提供了卷驱动程序,但是功能非常有限,从Docker 1.7版本开始,每个Container只允许一个卷驱动程序,并且无法将参数传递给卷。

另一方面,Kubernetes卷具有明确的生命周期,与使用它的Pod相同。因此,在Kubernetes中的卷可以比Pod中运行的任何Container都长,并且可以在Container重启或者销毁之后保留数据。Kubernetes支持多种类型的卷,Pod可以同时使用任意数量的卷。
kubernetes的Volume支持多种类型,比较常见的有下面几个:

  • 简单存储:EmptyDir、HostPath、NFS
  • 高级存储:PV、PVC
  • 配置存储:ConfigMap、Secret


从本质上讲,卷只是一个目录,可能包含一些数据,Pod中的容器可以访问它。要使用卷Pod需要通过.spec.volumes字段指定为Pod提供的卷,以及使用.spec.containers.volumeMounts 字段指定卷挂载的目录。从容器中的进程可以看到由Docker镜像和卷组成的文件系统视图,卷无法挂载其他卷或具有到其他卷的硬链接,Pod中的每个Container必须独立指定每个卷的挂载位置。

1.1.1基本存储

1.1.1.1EmptyDir

EmptyDir是最基础的Volume类型,一个EmptyDir就是Host上的一个空目录。
EmptyDir是在Pod被分配到Node时创建的,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为kubernetes会自动分配一个目录,当Pod销毁时, EmptyDir中的数据也会被永久删除。一般emptyDir卷用于Pod中的不同Container共享数据。它可以被挂载到相同或不同的路径上。 EmptyDir用途如下:

  • 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留
  • 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)

默认情况下,emptyDir卷支持节点上的任何介质,可能是SSD、磁盘或网络存储,具体取决于自身的环境。可以将emptyDir.medium字段设置为Memory,让Kubernetes使用tmpfs(内存支持的文件系统),虽然tmpfs非常快,但是tmpfs在节点重启时,数据同样会被清除,并且设置的大小会被计入到Container的内存限制当中。

接下来,通过一个容器之间文件共享的案例来使用一下EmptyDir。
在一个Pod中准备两个容器nginx和busybox,然后声明一个Volume分别挂在到两个容器的目录中,然后nginx容器负责向Volume中写日志,busybox中通过命令将日志内容读到控制台。
image.png

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: volume-emptydir
  5. namespace: dev
  6. spec:
  7. containers:
  8. - name: nginx
  9. image: nginx:1.17.1
  10. ports:
  11. - containerPort: 80
  12. volumeMounts: # 将logs-volume挂在到nginx容器中,对应的目录为 /var/log/nginx
  13. - name: logs-volume
  14. mountPath: /var/log/nginx
  15. - name: busybox
  16. image: busybox:1.30
  17. command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,动态读取指定文件中内容
  18. volumeMounts: # 将logs-volume 挂在到busybox容器中,对应的目录为 /logs
  19. - name: logs-volume
  20. mountPath: /logs
  21. volumes: # 声明volume, name为logs-volume,类型为emptyDir
  22. - name: logs-volume
  23. emptyDir: {}
  1. # 创建Pod
  2. [root@k8s-master01 ~]# kubectl create -f volume-emptydir.yaml
  3. pod/volume-emptydir created
  4. # 查看pod
  5. [root@k8s-master01 ~]# kubectl get pods volume-emptydir -n dev -o wide
  6. NAME READY STATUS RESTARTS AGE IP NODE ......
  7. volume-emptydir 2/2 Running 0 97s 10.42.2.9 node1 ......
  8. # 通过podIp访问nginx
  9. [root@k8s-master01 ~]# curl 10.42.2.9
  10. ......
  11. # 通过kubectl logs命令查看指定容器的标准输出
  12. [root@k8s-master01 ~]# kubectl logs -f volume-emptydir -n dev -c busybox
  13. 10.42.1.0 - - [27/Jun/2021:15:08:54 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

使用emptyDir卷的示例,直接指定emptyDir为{}即可:

  1. # cat nginx-deploy.yaml
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. labels:
  6. app: nginx
  7. name: nginx
  8. namespace: default
  9. spec:
  10. progressDeadlineSeconds: 600
  11. replicas: 2
  12. revisionHistoryLimit: 10
  13. selector:
  14. matchLabels:
  15. app: nginx
  16. strategy:
  17. rollingUpdate:
  18. maxSurge: 25%
  19. maxUnavailable: 25%
  20. type: RollingUpdate
  21. template:
  22. metadata:
  23. creationTimestamp: null
  24. labels:
  25. app: nginx
  26. spec:
  27. containers:
  28. - image: nginx:1.15.2
  29. imagePullPolicy: IfNotPresent
  30. name: nginx
  31. resources: {}
  32. terminationMessagePath: /dev/termination-log
  33. terminationMessagePolicy: File
  34. terminationMessagePath: /dev/termination-log
  35. terminationMessagePolicy: File
  36. volumeMounts:
  37. - mountPath: /opt
  38. name: share-volume
  39. - image: nginx:1.15.2
  40. imagePullPolicy: IfNotPresent
  41. name: nginx2
  42. command:
  43. - sh
  44. - -c
  45. - sleep 3600
  46. resources: {}
  47. terminationMessagePath: /dev/termination-log
  48. terminationMessagePolicy: File
  49. terminationMessagePath: /dev/termination-log
  50. terminationMessagePolicy: File
  51. volumeMounts:
  52. - mountPath: /mnt
  53. name: share-volume
  54. dnsPolicy: ClusterFirst
  55. restartPolicy: Always
  56. schedulerName: default-scheduler
  57. securityContext: {}
  58. terminationGracePeriodSeconds: 30
  59. volumes:
  60. - name: share-volume
  61. emptyDir: {}
  62. #medium: Memory

1.1.1.2HostPath

EmptyDir中数据不会被持久化,它会随着Pod的结束而销毁,如果想简单的将数据持久化到主机中,可以选择HostPath。
HostPath就是将Node主机中一个实际目录挂在到Pod中,以供容器使用,可以用于Pod自定义日志输出或访问Docker内部的容器等,这样的设计就可以保证Pod销毁了,但是数据依据可以存在于Node主机上。
image.png
创建一个volume-hostpath.yaml:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: volume-hostpath
  5. namespace: dev
  6. spec:
  7. containers:
  8. - name: nginx
  9. image: nginx:1.17.1
  10. ports:
  11. - containerPort: 80
  12. volumeMounts:
  13. - name: logs-volume
  14. mountPath: /var/log/nginx
  15. - name: busybox
  16. image: busybox:1.30
  17. command: ["/bin/sh","-c","tail -f /logs/access.log"]
  18. volumeMounts:
  19. - name: logs-volume
  20. mountPath: /logs
  21. volumes:
  22. - name: logs-volume
  23. hostPath:
  24. path: /root/logs
  25. type: DirectoryOrCreate # 目录存在就使用,不存在就先创建后使用
  1. 关于type的值的一点说明:
  2. type为空字符串:默认选项,意味着挂载hostPath卷之前不会执行任何检查。
  3. DirectoryOrCreate 如果给定的path不存在任何东西,那么将根据需要创建一个权限为0755的空目录,和Kubelet具有相同的组和权限。
  4. Directory 目录必须存在于给定的路径下。
  5. FileOrCreate 如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为0644,和Kubelet具有相同的组和所有权。
  6. File 文件,必须存在于给定路径中。
  7. Socket UNIX套接字,必须存在于给定路径中。
  8. CharDevice 字符设备,必须存在于给定路径中。
  9. BlockDevice 块设备,必须存在于给定路径中。
  1. # 创建Pod
  2. [root@k8s-master01 ~]# kubectl create -f volume-hostpath.yaml
  3. pod/volume-hostpath created
  4. # 查看Pod
  5. [root@k8s-master01 ~]# kubectl get pods volume-hostpath -n dev -o wide
  6. NAME READY STATUS RESTARTS AGE IP NODE ......
  7. pod-volume-hostpath 2/2 Running 0 16s 10.42.2.10 node1 ......
  8. #访问nginx
  9. [root@k8s-master01 ~]# curl 10.42.2.10
  10. [root@k8s-master01 ~]# kubectl logs -f volume-emptydir -n dev -c busybox
  11. # 接下来就可以去host的/root/logs目录下查看存储的文件了
  12. ### 注意: 下面的操作需要到Pod所在的节点运行(案例中是node1)
  13. [root@node1 ~]# ls /root/logs/
  14. access.log error.log
  15. # 同样的道理,如果在此目录下创建一个文件,到容器中也是可以看到的

使用hostPath卷的示例。将主机的/data目录挂载到Pod的/test-pd目录:

  1. # cat nginx-deploy.yaml
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. labels:
  6. app: nginx
  7. name: nginx
  8. namespace: default
  9. spec:
  10. progressDeadlineSeconds: 600
  11. replicas: 2
  12. revisionHistoryLimit: 10
  13. selector:
  14. matchLabels:
  15. app: nginx
  16. strategy:
  17. rollingUpdate:
  18. maxSurge: 25%
  19. maxUnavailable: 25%
  20. type: RollingUpdate
  21. template:
  22. metadata:
  23. creationTimestamp: null
  24. labels:
  25. app: nginx
  26. spec:
  27. containers:
  28. - image: nginx:1.15.2
  29. imagePullPolicy: IfNotPresent
  30. name: nginx
  31. resources: {}
  32. terminationMessagePath: /dev/termination-log
  33. terminationMessagePolicy: File
  34. terminationMessagePath: /dev/termination-log
  35. terminationMessagePolicy: File
  36. volumeMounts:
  37. - mountPath: /opt
  38. name: share-volume
  39. - mountPath: /etc/timezone
  40. name: timezone
  41. - mountPath: /etc/localtime
  42. name: time-config
  43. - image: nginx:1.15.2
  44. imagePullPolicy: IfNotPresent
  45. name: nginx2
  46. command:
  47. - sh
  48. - -c
  49. - sleep 3600
  50. resources: {}
  51. terminationMessagePath: /dev/termination-log
  52. terminationMessagePolicy: File
  53. terminationMessagePath: /dev/termination-log
  54. terminationMessagePolicy: File
  55. volumeMounts:
  56. - mountPath: /mnt
  57. name: share-volume
  58. dnsPolicy: ClusterFirst
  59. restartPolicy: Always
  60. schedulerName: default-scheduler
  61. securityContext: {}
  62. terminationGracePeriodSeconds: 30
  63. volumes:
  64. - name: share-volume
  65. emptyDir: {}
  66. #medium: Memory
  67. - name: timezone
  68. hostPath:
  69. path: /etc/timezone
  70. type: File
  71. - name: timezone
  72. - name: time-config #同步宿主机时间
  73. hostPath:
  74. path: /usr/share/zoneinfo/Asia/Shanghai
  75. type: File

1.1.1.3NFS

HostPath可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到了别的节点,又会出现问题了,此时需要准备单独的网络存储系统,比较常用的用NFS、CIFS。
NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样的话,无论Pod在节点上怎么转移,只要Node跟NFS的对接没问题,数据就可以成功访问。
NFS生产环境不建议使用,无法保证高可用
image.png
1.首先要准备nfs的服务器,这里为了简单,直接是master节点做nfs服务器

  1. # 在nfs上安装nfs服务
  2. apt install nfs-kernel-server -y
  3. #启动nfs
  4. systemctl restart nfs-kernel-server.service
  5. #查看nfs支持的版本
  6. cat /proc/fs/nfsd/versions
  7. # 创建一个共享目录
  8. mkdir -p /data/nfs
  9. # 将共享目录以读写权限暴露给192.168.68.0/24网段中的所有主机
  10. vim /etc/exports
  11. /root/data/nfs 192.168.68.0/24(rw,no_root_squash,no_subtree_check)
  12. # 启动nfs服务
  13. exportfs -r
  14. systemctl restart nfs-server

2.接下来,要在的每个node节点上都安装下nfs,这样的目的是为了node节点可以驱动nfs设备

  1. # 在node上安装nfs服务,注意不需要启动
  2. apt install nfs-kernel-server -y
  3. #在其它机器上测试挂载
  4. mount -t nfs 192.168.68.115:/data/nfs /mnt

3.接下来,就可以编写pod的配置文件了,创建volume-nfs.yaml

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: volume-nfs
  5. namespace: dev
  6. spec:
  7. containers:
  8. - name: nginx
  9. image: nginx:1.17.1
  10. ports:
  11. - containerPort: 80
  12. volumeMounts:
  13. - name: logs-volume
  14. mountPath: /var/log/nginx
  15. - name: busybox
  16. image: busybox:1.30
  17. command: ["/bin/sh","-c","tail -f /logs/access.log"]
  18. volumeMounts:
  19. - name: logs-volume
  20. mountPath: /logs
  21. volumes:
  22. - name: logs-volume
  23. nfs:
  24. server: 192.168.68.115 #nfs服务器地址
  25. path: /data/nfs #共享文件路径

4.最后,运行下pod,观察结果

  1. # 创建pod
  2. [root@k8s-master01 ~]# kubectl create -f volume-nfs.yaml
  3. pod/volume-nfs created
  4. # 查看pod
  5. [root@k8s-master01 ~]# kubectl get pods volume-nfs -n dev
  6. NAME READY STATUS RESTARTS AGE
  7. volume-nfs 2/2 Running 0 2m9s
  8. # 查看nfs服务器上的共享目录,发现已经有文件了
  9. [root@k8s-master01 ~]# ls /data/nfs
  10. access.log error.log

实验2:
创建nginx-deploy-nfs.yaml文件

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. labels:
  5. app: nginx
  6. name: nginx-nfs
  7. namespace: default
  8. spec:
  9. progressDeadlineSeconds: 600
  10. replicas: 2
  11. revisionHistoryLimit: 10
  12. selector:
  13. matchLabels:
  14. app: nginx
  15. strategy:
  16. rollingUpdate:
  17. maxSurge: 25%
  18. maxUnavailable: 25%
  19. type: RollingUpdate
  20. template:
  21. metadata:
  22. creationTimestamp: null
  23. labels:
  24. app: nginx
  25. spec:
  26. containers:
  27. - image: nginx:1.15.2
  28. imagePullPolicy: IfNotPresent
  29. name: nginx
  30. resources: {}
  31. terminationMessagePath: /dev/termination-log
  32. terminationMessagePolicy: File
  33. terminationMessagePath: /dev/termination-log
  34. terminationMessagePolicy: File
  35. volumeMounts:
  36. - mountPath: /opt
  37. name: share-volume
  38. - mountPath: /etc/timezone
  39. name: timezone
  40. - mountPath: /etc/localtime
  41. name: time-config
  42. - image: nginx:1.15.2
  43. imagePullPolicy: IfNotPresent
  44. name: nginx2
  45. command:
  46. - sh
  47. - -c
  48. - sleep 3600
  49. resources: {}
  50. terminationMessagePath: /dev/termination-log
  51. terminationMessagePolicy: File
  52. terminationMessagePath: /dev/termination-log
  53. terminationMessagePolicy: File
  54. volumeMounts:
  55. - mountPath: /mnt
  56. name: share-volume
  57. - mountPath: /var/log/nginx
  58. name: nfs-volume
  59. dnsPolicy: ClusterFirst
  60. restartPolicy: Always
  61. schedulerName: default-scheduler
  62. securityContext: {}
  63. terminationGracePeriodSeconds: 30
  64. volumes:
  65. - name: share-volume
  66. emptyDir: {}
  67. #medium: Memory
  68. - name: timezone
  69. hostPath:
  70. path: /etc/timezone
  71. type: File
  72. - name: time-config
  73. hostPath:
  74. path: /usr/share/zoneinfo/Asia/Shanghai
  75. type: File
  76. - name: nfs-volume
  77. nfs:
  78. server: 192.168.68.115
  79. path: /data/nfs/nginx-log

创建容器
kubectl create -f nginx-deploy-nfs.yaml
进入容器并创建一个123.txt文件
image.png
返回宿主机文件夹目录查看文件
image.png

1.1.2高级存储

Volumes无法满足需求
image.png
Volume无法解决的问题:

  1. 当某个数据卷不再被挂载使用时,里面的数据如何处理?
  2. 如果想要实现只读挂载如何处理?
  3. 如果想要只能一个Pod挂载如何处理?
  4. 如何只允许某个Pod使用10G的空间?

为了能够屏蔽底层存储实现的细节,方便用户使用, kubernetes引入PV和PVC两种资源对象。

  1. PV(Persistent Volume)是持久化卷的意思,是对底层的共享存储的一种抽象。一般情况下PV由kubernetes管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接。
  2. PersistentVolume:简称PV,是由Kubernetes管理员设置的存储,可以配置Ceph、NFS、GlusterFS等常用存储配置,相对于Volume配置,提供了更多的功能,比如生命周期的管理、大小的限制。PV分为静态和动态。
  3. PVC(Persistent Volume Claim)是持久卷声明的意思,是用户对于存储需求的一种声明。换句话说,PVC其实就是用户向kubernetes系统发出的一种资源需求申请。
  4. PersistentVolumeClaim:简称PVC,是对存储PV的请求,表示需要什么类型的PV,需要存储的技术人员只需要配置PVC即可使用存储,或者Volume配置PVC的名称即可。

image.png
image.png
使用了PV和PVC之后,工作可以得到进一步的细分:

  • 存储:存储工程师维护
  • PV: kubernetes管理员维护
  • PVC:kubernetes用户维护

官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/

1.1.2.1 PV

PV是存储资源的抽象,下面是资源清单文件:

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: pv2
  5. spec:
  6. nfs: # 存储类型,与底层真正存储对应
  7. capacity: # 存储能力,目前只支持存储空间的设置
  8. storage: 2Gi
  9. accessModes: # 访问模式
  10. storageClassName: # 存储类别
  11. persistentVolumeReclaimPolicy: # 回收策略

PV 的关键配置参数说明:

  • 存储类型

底层实际存储的类型,kubernetes支持多种存储类型,每种存储类型的配置都有所差异

  • 存储能力(capacity)

目前只支持存储空间的设置( storage=1Gi ),不过未来可能会加入IOPS、吞吐量等指标的配置

  • 访问模式(accessModes)

用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:需要注意的是,底层不同的存储类型可能支持的访问模式不同

  • ReadWriteOnce(RWO):可以被单节点以读写模式挂载,命令行中可以被缩写为RWO。
  • ReadOnlyMany(ROX): 可以被多个节点以只读模式挂载,命令行中可以被缩写为ROX。
  • ReadWriteMany(RWX):可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX。
  • storageClassName:PV的类,一个特定类型的PV只能绑定到特定类别的PVC;

官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes

  • 回收策略(persistentVolumeReclaimPolicy)

当PV不再被使用了之后,对其的处理方式。目前支持三种策略:需要注意的是,底层不同的存储类型可能支持的回收策略不同

  • Retain (保留) 保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,PV被视为已释放,管理员可以手动回收卷。
  • Recycle(回收) 回收,如果Volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略将来会被弃用,目前只有NFS和HostPath支持该策略。
  • Delete (删除) 删除,如果Volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete,目前支持Delete的存储后端包括AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder等。

通过persistentVolumeReclaimPolicy: Recycle字段配置
官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaim-policy

  • 存储类别

PV可以通过storageClassName参数指定一个存储类别

  • 具有特定类别的PV只能与请求了该类别的PVC进行绑定
  • 未设定类别的PV则只能与不请求任何类别的PVC进行绑定
    • 存储分类
  • 文件存储:一些数据可能需要被多个节点使用,比如用户的头像、用户上传的文件等,实现方式:NFS、NAS、FTP、CephFS等。
  • 块存储:一些数据只能被一个节点使用,或者是需要将一块裸盘整个挂载使用,比如数据库、Redis等,实现方式:Ceph、GlusterFS、公有云。
  • 对象存储:由程序代码直接实现的一种存储方式,云原生应用无状态化常用的实现方式,实现方式:一般是符合S3协议的云存储,比如AWS的S3存储、Minio、七牛云等。
    • 状态(status)

一个 PV 的生命周期中,可能会处于4中不同的阶段:

  • Available(可用): 表示可用状态,还未被任何 PVC 绑定
  • Bound(已绑定): 表示 PV 已经被 PVC 绑定
  • Released(已释放): 表示 PVC 被删除,但是资源还未被集群重新声明
  • Failed(失败): 表示该 PV 的自动回收失败
    • PV配置示例-NFS/NAS ``` apiVersion: v1 kind: PersistentVolume metadata: name: pv-nfs spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes:
    • ReadWriteMany persistentVolumeReclaimPolicy: Recycle storageClassName: nfs-slow mountOptions:
    • hard
    • nfsvers=4.1 nfs: path: /data/k8s-data/testDir server: 192.168.68.119

capacity:容量配置 volumeMode:卷的模式,目前支持Filesystem(文件系统) 和 Block(块),其中Block类型需要后端存储支持,默认为文件系统 accessModes:该PV的访问模式 storageClassName:PV的类,一个特定类型的PV只能绑定到特定类别的PVC; persistentVolumeReclaimPolicy:回收策略 mountOptions:非必须,新版本中已弃用 nfs:NFS服务配置,包括以下两个选项 path:NFS上的共享目录 server:NFS的IP地址

pv与pvc绑定 cat nfs-pv-pvc.yaml

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-pvc spec: accessModes:

  1. - ReadWriteMany

volumeMode: Filesystem storageClassName: nfs-slow resources: requests: storage: 5Gi

挂载PVC root@k8s-master01:~/yaml# cat nginx-deploy-nfs-pvc.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-nfs-pvc namespace: default spec: progressDeadlineSeconds: 600 replicas: 2 revisionHistoryLimit: 10 selector: matchLabels: app: nginx strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx spec: containers:

  1. - image: nginx:1.15.2
  2. imagePullPolicy: IfNotPresent
  3. name: nginx
  4. resources: {}
  5. terminationMessagePath: /dev/termination-log
  6. terminationMessagePolicy: File
  7. terminationMessagePath: /dev/termination-log
  8. terminationMessagePolicy: File
  9. volumeMounts:
  10. - mountPath: /opt
  11. name: share-volume
  12. - mountPath: /etc/timezone
  13. name: timezone
  14. - mountPath: /etc/localtime
  15. name: time-config
  16. - mountPath: /tmp/pvc
  17. name: pvc-nfs
  18. - image: nginx:1.15.2
  19. imagePullPolicy: IfNotPresent
  20. name: nginx2
  21. command:
  22. - sh
  23. - -c
  24. - sleep 3600
  25. resources: {}
  26. terminationMessagePath: /dev/termination-log
  27. terminationMessagePolicy: File
  28. terminationMessagePath: /dev/termination-log
  29. terminationMessagePolicy: File
  30. volumeMounts:
  31. - mountPath: /mnt
  32. name: share-volume
  33. - mountPath: /var/log/nginx
  34. name: nfs-volume
  35. dnsPolicy: ClusterFirst
  36. restartPolicy: Always
  37. schedulerName: default-scheduler
  38. securityContext: {}
  39. terminationGracePeriodSeconds: 30
  40. volumes:
  41. - name: share-volume
  42. emptyDir: {}
  43. #medium: Memory
  44. - name: timezone
  45. hostPath:
  46. path: /etc/timezone
  47. type: File
  48. - name: time-config
  49. hostPath:
  50. path: /usr/share/zoneinfo/Asia/Shanghai
  51. type: File
  52. - name: nfs-volume
  53. nfs:
  54. server: 192.168.68.115
  55. path: /data/nfs/nginx-log
  56. - name: pvc-nfs
  57. persistentVolumeClaim:
  58. claimName: nfs-pvc
  1. - **PV配置示例-HostPath**

kind: PersistentVolume apiVersion: v1 metadata: name: task-pv-volume labels: type: local spec: storageClassName: hostpath capacity: storage: 10Gi accessModes:

  1. - ReadWriteOnce

hostPath: path: “/mnt/data”

hostPath:hostPath服务配置 path:宿主机路径

  1. - **PV配置示例-CephRBD**

apiVersion: v1 kind: PersistentVolume metadata: name: ceph-rbd-pv spec: capacity: storage: 1Gi storageClassName: ceph-fast accessModes:

  1. - ReadWriteOnce

rbd: monitors:

  1. - 192.168.1.123:6789
  2. - 192.168.1.124:6789
  3. - 192.168.1.125:6789
  4. pool: rbd
  5. image: ceph-rbd-pv-test
  6. user: admin
  7. secretRef:
  8. name: ceph-secret
  9. fsType: ext4
  10. readOnly: false

monitors:Ceph的monitor节点的IP pool:所用Ceph Pool的名称,可以使用ceph osd pool ls查看 image:Ceph块设备中的磁盘映像文件,可以使用rbd create POOL_NAME/IMAGE_NAME —size 1024创建,使用rbd list POOL_NAME查看 user:Rados的用户名,默认是admin secretRef:用于验证Ceph身份的密钥 fsType:文件类型,可以是ext4、XFS等 readOnly:是否是只读挂载

  1. **实验**<br />使用NFS作为存储,来演示PV的使用,创建3PV,对应NFS中的3个暴露的路径。
  2. 1. 准备NFS环境

创建目录

mkdir /root/data/{pv1,pv2,pv3} -pv

暴露服务

vim /etc/exports /root/data/pv1 192.168.68.0/24(rw,no_root_squash,no_subtree_check) /root/data/pv2 192.168.68.0/24(rw,no_root_squash,no_subtree_check) /root/data/pv3 192.168.68.0/24(rw,no_root_squash,no_subtree_check)

重启服务

systemctl restart nfs-kernel-server.service

  1. 2. 创建pv.yaml

apiVersion: v1 kind: PersistentVolume metadata: name: pv1 spec: capacity: storage: 1Gi accessModes:

  • ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: path: /root/data/pv1 server: 192.168.68.115

apiVersion: v1 kind: PersistentVolume metadata: name: pv2 spec: capacity: storage: 2Gi accessModes:

  • ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: path: /root/data/pv2 server: 192.168.68.115

apiVersion: v1 kind: PersistentVolume metadata: name: pv3 spec: capacity: storage: 3Gi accessModes:

  • ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: path: /root/data/pv3 server: 192.168.68.115

    创建 pv

    kubectl create -f pv.yaml

查看pv

kubectl get pv -o wide NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE pv1 1Gi RWX Retain Available 13s Filesystem pv2 2Gi RWX Retain Available 13s Filesystem pv3 3Gi RWX Retain Available 13s Filesystem

  1. <a name="HTdBJ"></a>
  2. ##### 1.1.2.2 PVC
  3. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/719835/1648264848957-6c8fb039-b916-4708-a568-0b5c83ccdc56.png#clientId=u1b95db0b-f783-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=872&id=u6899495a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1090&originWidth=1715&originalType=binary&ratio=1&rotation=0&showTitle=false&size=2327153&status=done&style=none&taskId=u0b329eac-d03b-4334-b1ac-dd85ae6dce3&title=&width=1372)<br />PVC是资源的申请,用来声明对存储空间、访问模式、存储类别需求信息。下面是资源清单文件:

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc namespace: dev spec: accessModes: # 访问模式 selector: # 采用标签对PV选择 storageClassName: # 存储类别 resources: # 请求空间 requests: storage: 5Gi

  1. PVC 的关键配置参数说明:
  2. - **访问模式(accessModes)**
  3. 用于描述用户应用对存储资源的访问权限
  4. - **选择条件(selector)**通过Label Selector的设置,可使PVC对于系统中己存在的PV进行筛选
  5. - **存储类别(storageClassName)**PVC在定义时可以设定需要的后端存储的类别,只有设置了该classpv才能被系统选出
  6. - **资源请求(Resources )**描述对存储资源的请求
  7. PVC创建和挂载失败的原因:
  8. - PVC一直Pending的原因:
  9. - PVC的空间申请大小大于PV的大小
  10. - PVCStorageClassName没有和PV的一致
  11. - PVCaccessModesPV的不一致
  12. - 挂载PVCPod一直处于Pending
  13. - PVC没有创建成功/PVC不存在
  14. - PVCPod不在同一个Namespace
  15. 删除PVC后-->k8s会创建一个用于回收的pod-->根据PV的回收策略进行PV的回收-->回收完成后,PV的状态就会变成可绑定的状态也就是空闲状态-->其他的pending状态的pvc,如果匹配到这个pvc,就能和这个PV进行绑定。
  16. **实验**
  17. - 创建pvc.yaml,申请pv

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc1 namespace: dev spec: accessModes:

  • ReadWriteMany resources: requests: storage: 1Gi

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc2 namespace: dev spec: accessModes:

  • ReadWriteMany resources: requests: storage: 1Gi

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc3 namespace: dev spec: accessModes:

  • ReadWriteMany resources: requests: storage: 1Gi

    创建pvc

    kubectl create -f pvc.yaml

查看pvc

root@k8s-master01:~/yaml# kubectl get pvc -n dev -o wide NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE pvc1 Bound pv1 1Gi RWX 19s Filesystem pvc2 Bound pv2 2Gi RWX 19s Filesystem pvc3 Bound pv3 3Gi RWX 19s Filesystem

查看pv

root@k8s-master01:~/yaml# kubectl get pv -o wide NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE pv1 1Gi RWX Retain Bound dev/pvc1 5m27s Filesystem pv2 2Gi RWX Retain Bound dev/pvc2 5m27s Filesystem pv3 3Gi RWX Retain Bound dev/pvc3 5m27s Filesystem

  1. - 创建pods-pv.yaml, 使用pv

apiVersion: v1 kind: Pod metadata: name: pod1 namespace: dev spec: containers:

  • name: busybox image: busybox:1.30 command: [“/bin/sh”,”-c”,”while true;do echo pod1 >> /root/out.txt; sleep 10; done;”] volumeMounts:
    • name: volume mountPath: /root/ volumes:
    • name: volume persistentVolumeClaim: claimName: pvc1 readOnly: false

apiVersion: v1 kind: Pod metadata: name: pod2 namespace: dev spec: containers:

  • name: busybox image: busybox:1.30 command: [“/bin/sh”,”-c”,”while true;do echo pod2 >> /root/out.txt; sleep 10; done;”] volumeMounts:
    • name: volume mountPath: /root/ volumes:
    • name: volume persistentVolumeClaim: claimName: pvc2 readOnly: false

      创建pod

      kubectl create -f pods-pv.yaml

查看pod

kubectl get pods -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod1 1/1 Running 0 38s 172.27.14.203 k8s-node02 pod2 1/1 Running 0 37s 172.25.214.203 k8s-node03

查看pvc

kubectl get pvc -n dev -o wide NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE pvc1 Bound pv1 1Gi RWX 2m44s Filesystem pvc2 Bound pv2 2Gi RWX 2m44s Filesystem pvc3 Bound pv3 3Gi RWX 2m44s Filesystem

查看pv

kubectl get pv -n dev -o wide NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE pv1 1Gi RWX Retain Bound dev/pvc1 8m2s Filesystem pv2 2Gi RWX Retain Bound dev/pvc2 8m2s Filesystem pv3 3Gi RWX Retain Bound dev/pvc3 8m2s Filesystem

查看nfs中的文件存储

root@k8s-master01:~/yaml# more /root/data/pv1/out.txt pod1 pod1 pod1 pod1 pod1 pod1 pod1 pod1 pod1 pod1 pod1 pod1 root@k8s-master01:~/yaml# cat /root/data/pv2/out.txt pod2 pod2 pod2 pod2 pod2 pod2 pod2 pod2 pod2 pod2 pod2 pod2

  1. <a name="zNKUQ"></a>
  2. ##### 1.1.2.3 生命周期
  3. PVC和PV是一一对应的,PV和PVC之间的相互作用遵循以下生命周期:
  4. - **资源供应**:管理员手动创建底层存储和PV
  5. - **资源绑定**:用户创建PVC,kubernetes负责根据PVC的声明去寻找PV,并绑定在用户定义好PVC之后,系统将根据PVC对存储资源的请求在已存在的PV中选择一个满足条件的PV一旦绑定到某个PVC上,就会被这个PVC独占,不能再与其他PVC进行绑定了
  6. - 一旦找到,就将该PV与用户定义的PVC进行绑定,用户的应用就可以使用这个PVC了
  7. - 如果找不到,PVC则会无限期处于Pending状态,直到等到系统管理员创建了一个符合其要求的PV
  8. - **资源使用**:用户可在pod中像volume一样使用pvcPod使用Volume的定义,将PVC挂载到容器内的某个路径进行使用。
  9. - **资源释放**:用户删除pvc来释放pv当存储资源使用完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为“已释放”,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还被留在存储设备上,只有在清除之后该PV才能再次使用。
  10. - **资源回收**:kubernetes根据pv设置的回收策略进行资源的回收对于PV,管理员可以设定回收策略,用于设置与之绑定的PVC释放资源之后如何处理遗留数据的问题。只有PV的存储空间完成回收,才能供新的PVC绑定和使用。
  11. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/719835/1648265576790-a5dbadcb-899b-444e-9ec0-285d0548136c.png#clientId=u1b95db0b-f783-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=429&id=ud5c94c71&margin=%5Bobject%20Object%5D&name=image.png&originHeight=536&originWidth=1185&originalType=binary&ratio=1&rotation=0&showTitle=false&size=204389&status=done&style=none&taskId=ube48a974-589e-48ec-877c-7feee154e8d&title=&width=948)
  12. <a name="SLN5D"></a>
  13. ## 2.高级调度
  14. <a name="bS3Ol"></a>
  15. ### 2.1 CronJob计划任务
  16. CronJob用于以时间为基准周期性地执行任务,这些自动化任务和运行在Linux或UNIX系统上的CronJob一样。CronJob对于创建定期和重复任务非常有用,例如执行备份任务、周期性调度程序接口、发送电子邮件等。<br />对于Kubernetes 1.8以前的版本,需要添加--runtime-config=batch/v2alpha1=true参数至APIServer中,然后重启APIServer和Controller Manager用于启用API,对于1.8以后的版本无须修改任何参数,可以直接使用,本节的示例基于1.8以上的版本。<br />在k8s里面运行周期性的计划任务,cronjob。
  17. - * * * * * 分时日月周
  18. - 计划任务可能需要调用应用的接口。
  19. - 计划任务可能需要依赖某些环境。
  20. - php xxx ,直接用php项目的镜像进行执行计划任务。
  21. - php-wordpress:v1.0.1
  22. - cronjob被调用的时间,是用的controller-manager的时间
  23. <a name="OMKRT"></a>
  24. #### 1.创建cronjob
  25. 创建CronJob有两种方式,一种是直接使用kubectl创建,一种是使用yaml文件创建。<br />使用kubectl创建CronJob的命令如下:<br />`kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster" 命令报错`<br />对应的yaml文件如下:cronjob.yaml<br />kubectl create -f cronjob.yaml

apiVersion: batch/v1beta1 kind: CronJob metadata: name: hello spec: schedule: “/1 *” jobTemplate: spec: template: spec: containers:

  1. - name: hello
  2. image: busybox
  3. args:
  4. - /bin/sh
  5. - -c
  6. - date; echo Hello from the Kubernetes cluster
  7. restartPolicy: OnFailure
  1. s<br />说明:本例创建一个每分钟执行一次、打印当前时间和Hello from the Kubernetes cluster的计划任务。
  2. 查看创建的CronJob

root@k8s-master01:~/yaml# kubectl get cj NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello /1 * False 0 26s 2m29s

  1. 等待1分钟可以查看执行的任务(Jobs):

root@k8s-master01:~/yaml# kubectl get job NAME COMPLETIONS DURATION AGE hello-27472436 1/1 21s 3m7s hello-27472437 1/1 20s 2m7s hello-27472438 1/1 20s 67s hello-27472439 0/1 7s 7s

  1. CronJob每次调用任务的时候会创建一个Pod执行命令,执行完任务后,Pod状态就会变成Completed,如下所示:

root@k8s-master01:~/yaml# kubectl get pod NAME READY STATUS RESTARTS AGE hello-27472437-ck9zc 0/1 Completed 0 3m14s hello-27472438-gsfr7 0/1 Completed 0 2m14s hello-27472439-ms6sw 0/1 Completed 0 74s hello-27472440-tgfbh 0/1 ContainerCreating 0 14s

  1. 可以通过logs查看Pod的执行日志:

root@k8s-master01:~/yaml# kubectl logs -f hello-27472440-tgfbh Sun Mar 27 02:00:17 UTC 2022 Hello from the Kubernetes cluster

  1. 如果要删除CronJob,直接使用delete即可:

kubectl delete -f cronjob.yaml

  1. <a name="nphmv"></a>
  2. #### 2.可用参数的配置
  3. 定义一个CronJob的yaml文件如下:

apiVersion: v1 items:

  • apiVersion: batch/v1beta1 kind: CronJob metadata: labels:

    1. run: hello

    name: hello namespace: default spec: concurrencyPolicy: Allow failedJobsHistoryLimit: 1 jobTemplate:

    1. metadata:
    2. creationTimestamp: null
    3. spec:
    4. template:
    5. metadata:
    6. creationTimestamp: null
    7. labels:
    8. run: hello
    9. spec:
    10. containers:
    11. - args:
    12. - /bin/sh
    13. - -c
    14. - date; echo Hello from the Kubernetes cluster
    15. image: busybox
    16. imagePullPolicy: Always
    17. name: hello
    18. resources: {}
    19. terminationMessagePath: /dev/termination-log
    20. terminationMessagePolicy: File
    21. dnsPolicy: ClusterFirst
    22. restartPolicy: OnFailure
    23. schedulerName: default-scheduler
    24. securityContext: {}
    25. terminationGracePeriodSeconds: 30

    schedule: ‘/1 *’ successfulJobsHistoryLimit: 3 suspend: false ``` 其中各参数的说明如下,可以按需修改:

  • schedule:调度周期,和Linux一致,分别是分时日月周。

  • restartPolicy:重启策略,和Pod一致。
  • concurrencyPolicy:并发调度策略。可选参数如下:
    • Allow:允许同时运行多个任务。
    • Forbid:不允许并发运行,如果之前的任务尚未完成,新的任务不会被创建。
    • Replace:如果之前的任务尚未完成,新的任务会替换的之前的任务。
  • suspend:如果设置为true,则暂停后续的任务,默认为false。
  • successfulJobsHistoryLimit:保留多少已完成的任务,按需配置。
  • failedJobsHistoryLimit:保留多少失败的任务。

相对于Linux上的计划任务,Kubernetes的CronJob更具有可配置性,并且对于执行计划任务的环境只需启动相对应的镜像即可。比如,如果需要Go或者PHP环境执行任务,就只需要更改任务的镜像为Go或者PHP即可,而对于Linux上的计划任务,则需要安装相对应的执行环境。此外,Kubernetes的CronJob是创建Pod来执行,更加清晰明了,查看日志也比较方便。可见,Kubernetes的CronJob更加方便和简单。

2.2污点和容忍Taint&Toleration

1.介绍

Taint&Toleration
1.在不同的机房
2.在不同的城市
3.不一样的配置
GPU服务器
纯固态硬盘的服务器
NodeSelect
Gpu-server:ture
Ssd-server:ture
Normal-server:ture

污点和容忍的说明
Taint在一类服务器上打上污点,让不能容忍这个污点的pod不能部署在打了污点的服务器上。
Master节点不应该部署系统pod之外的任何pod

2.Taint&Toleration

Taint能够使节点排斥一类特定的Pod,Taint和Toleration相互配合可以用来避免Pod被分配到不合适的节点,比如Master节点不允许部署系统组件之外的其他Pod。每个节点上都可以应用一个或多个Taint,这表示对于那些不能容忍这些Taint的Pod是不会被该节点接受的。如果将Toleration应用于Pod上,则表示这些Pod可以(但不要求)被调度到具有匹配Taint的节点上。

1. 概念

给节点增加一个Taint:
kubectl taint nodes k8s-master01 master-test=test:NoSchedule
删除一个Taint:
kubectl taint nodes k8s-master01 master-test-
上述命令给k8s-master01增加一个Taint,它的master-test对应的就是键,test对应就是值,effect对应的就是NoSchedule。这表明只有和这个Taint相匹配的Toleration的Pod才能够被分配到k8s-node01节点上。按如下方式在PodSpec中定义Pod的Toleration,就可以将Pod部署到该节点上。
方式一:

  1. tolerations:
  2. - key: "master-test"
  3. operator: "Equal"
  4. value: "test"
  5. effect: "NoSchedule"

方式二:

  1. tolerations:
  2. - key: "master-test"
  3. operator: "Exists"
  4. effect: "NoSchedule"

一个Toleration和一个Taint相匹配是指它们有一样的key和effect,并且如果operator是Exists(此时toleration不指定value)或者operator是Equal,则它们的value应该相等。

注意两种情况:

  • 如果一个Toleration的key为空且operator为Exists,表示这个Toleration与任意的key、value和effect都匹配,即这个Toleration能容忍任意的Taint: ``` tolerations:
  • operator: “Exists” ```

  • 如果一个Toleration的effect为空,则key与之相同的相匹配的Taint的effect可以是任意值: ``` tolerations:

  • key: “key” operator: “Exists” ``` 上述例子使用到effect的一个值NoSchedule,也可以使用PreferNoSchedule,该值定义尽量避免将Pod调度到存在其不能容忍的Taint的节点上,但并不是强制的。effect的值还可以设置为NoExecute。

一个节点可以设置多个Taint,也可以给一个Pod添加多个Toleration。Kubernetes处理多个Taint和Toleration的过程就像一个过滤器:从一个节点的所有Taint开始遍历,过滤掉那些Pod中存在与之相匹配的Toleration的Taint。余下未被过滤的Taint的effect值决定了Pod是否会被分配到该节点,特别是以下情况:

  • 如果未被过滤的Taint中存在一个以上effect值为NoSchedule的Taint,则Kubernetes不会将Pod分配到该节点。NoSchedule禁止调度
  • 如果未被过滤的Taint中不存在effect值为NoExecute的Taint,但是存在effect值为PreferNoSchedule的Taint,则Kubernetes会尝试将Pod分配到该节点。NoExecute如果不符合这个污点,会立马被驱逐
  • 如果未被过滤的Taint中存在一个以上effect值为NoExecute的Taint,则Kubernetes不会将Pod分配到该节点(如果Pod还未在节点上运行),或者将Pod从该节点驱逐(如果Pod已经在节点上运行)。

例如,假设给一个节点添加了以下的Taint:

  1. kubectl taint nodes k8s-node01 key1=value1:NoSchedule
  2. kubectl taint nodes k8s-node01 key1=value1:NoExecute
  3. kubectl taint nodes k8s-node01 key2=value2:NoSchedule

然后存在一个Pod,它有两个Toleration:

  1. tolerations:
  2. - key: "key1"
  3. operator: "Equal"
  4. value: "value1"
  5. effect: "NoSchedule"
  6. - key: "key1"
  7. operator: "Equal"
  8. value: "value1"
  9. effect: "NoExecute"

在上述例子中,该Pod不会被分配到上述节点,因为没有匹配第三个Taint。但是如果给节点添加上述3个Taint之前,该Pod已经在上述节点中运行,那么它不会被驱逐,还会继续运行在这个节点上,因为第3个Taint是唯一不能被这个Pod容忍的。
通常情况下,如果给一个节点添加了一个effect值为NoExecute的Taint,则任何不能容忍这个Taint的Pod都会马上被驱逐,任何可以容忍这个Taint的Pod都不会被驱逐。但是,如果Pod存在一个effect值为NoExecute的Toleration指定了可选属性tolerationSeconds的值,则该值表示是在给节点添加了上述Taint之后Pod还能继续在该节点上运行的时间,例如:

  1. tolerations:
  2. - key: "key1"
  3. operator: "Equal"
  4. value: "value1"
  5. effect: "NoExecute"
  6. tolerationSeconds: 3600

表示如果这个Pod正在运行,然后一个匹配的Taint被添加到其所在的节点,那么Pod还将继续在节点上运行3600秒,然后被驱逐。如果在此之前上述Taint被删除了,则Pod不会被驱逐。
删除一个Taint:
kubectl taint nodes k8s-node01 key1:NoExecute-
查看Taint:
kubectl describe node k8s-node01 | grep Tain

2. 用例

通过Taint和Toleration可以灵活地让Pod避开某些节点或者将Pod从某些节点被驱逐。下面是几种情况。

(1)专用节点

如果想将某些节点专门分配给特定的一组用户使用,可以给这些节点添加一个Taint(kubectl taint nodes nodename dedicated=groupName:NoSchedule),然后给这组用户的Pod添加一个相对应的Toleration。拥有上述Toleration的Pod就能够被分配到上述专用节点,同时也能够被分配到集群中的其他节点。如果只希望这些Pod只能分配到上述专用节点中,那么还需要给这些专用节点另外添加一个和上述Taint类似的Label(例如:dedicated=groupName),然后给Pod增加节点亲和性要求或者使用NodeSelector,就能将Pod只分配到添加了dedicated=groupName标签的节点上。

(2)特殊硬件的节点

在部分节点上配备了特殊硬件(比如GPU)的集群中,我们只允许特定的Pod才能部署在这些节点上。这时可以使用Taint进行控制,添加Taint如kubectl taint nodes nodename special=true:NoSchedule或者kubectl taint nodes nodename special=true:PreferNoSchedule,然后给需要部署在这些节点上的Pod添加相匹配的Toleration即可。

(3)基于Taint的驱逐

属于alpha特性,在每个Pod中配置在节点出现问题时的驱逐行为。

3. 基于Taint的驱逐

之前提到过Taint的effect值NoExecute,它会影响已经在节点上运行的Pod。如果Pod不能忍受effect值为NoExecute的Taint,那么Pod将会被马上驱逐。如果能够忍受effect值为NoExecute的Taint,但是在Toleration定义中没有指定tolerationSeconds,则Pod还会一直在这个节点上运行。

在Kubernetes 1.6版以后已经支持(alpha)当某种条件为真时,Node Controller会自动给节点添加一个Taint,用以表示节点的问题。当前内置的Taint包括:

  • node.kubernetes.io/not-ready:节点未准备好,相当于节点状态Ready的值为False。
  • node.kubernetes.io/unreachable:Node Controller访问不到节点,相当于节点状态Ready的值为Unknown。
  • node.kubernetes.io/out-of-disk:节点磁盘耗尽。
  • node.kubernetes.io/memory-pressure:节点存在内存压力。
  • node.kubernetes.io/disk-pressure:节点存在磁盘压力。
  • node.kubernetes.io/network-unavailable:节点网络不可达。
  • node.kubernetes.io/unschedulable:节点不可调度。
  • node.cloudprovider.kubernetes.io/uninitialized:如果Kubelet启动时指定了一个外部的cloudprovider,它将给当前节点添加一个Taint将其标记为不可用。在cloud-controller-manager的一个controller初始化这个节点后,Kubelet将删除这个Taint。

使用这个alpha功能特性,结合tolerationSeconds,Pod就可以指定当节点出现一个或全部上述问题时,Pod还能在这个节点上运行多长时间。
比如,一个使用了很多本地状态的应用程序在网络断开时,仍然希望停留在当前节点上运行一段时间,愿意等待网络恢复以避免被驱逐。在这种情况下,Pod的Toleration可以这样配置:

  1. tolerations:
  2. - key: "node.alpha.kubernetes.io/unreachable"
  3. operator: "Exists"
  4. effect: "NoExecute"
  5. tolerationSeconds: 6000

Kubernetes会自动给Pod添加一个key为node.kubernetes.io/not-ready的Toleration并配置tolerationSeconds=300,同样也会给Pod添加一个key为node.kubernetes.io/unreachable的Toleration并配置tolerationSeconds=300,除非用户自定义了上述key,否则会采用这个默认设置。

这种自动添加Toleration的机制保证了在其中一种问题被检测到时,Pod默认能够继续停留在当前节点运行5分钟。这两个默认Toleration是由DefaultTolerationSeconds admission controller添加的。
DaemonSet中的Pod被创建时,针对以下Taint自动添加的NoExecute的Toleration将不会指定tolerationSeconds:

  • node.alpha.kubernetes.io/unreachable
  • node.kubernetes.io/not-ready

这保证了出现上述问题时DaemonSet中的Pod永远不会被驱逐。

2.3初始化容器InitContainer

1.初始化容器的用途

  • Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码;
  • Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低;
  • Init容器可以以root身份运行,执行一些高权限命令;
  • Init容器相关操作执行完成以后即退出,不会给业务容器带来安全隐患。

在主应用启动之前,做一些初始化的操作,比如创建文件、修改内核参数、等待依赖程序启动或其他需要在主程序启动之前需要做的工作

2.初始化容器和PostStart区别

PostStart:依赖主应用的环境,而且并不一定先于Command运行
InitContainer:不依赖主应用的环境,可以有更高的权限和更多的工具,一定会在主应用启动之前完成

3.初始化容器和普通容器的区别

Init 容器与普通的容器非常像,除了如下几点:

  • 它们总是运行到完成;
  • 上一个运行完成才会运行下一个;
  • 如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止,但是Pod 对应的 restartPolicy 值为 Never,Kubernetes 不会重新启动 Pod。
  • Init 容器不支持 lifecycle、livenessProbe、readinessProbe 和 startupProbe

查看示例:

  1. root@k8s-master01:~/yaml# cat nginx-deploy-initcontainer.yaml
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. labels:
  6. app: nginx
  7. name: nginx
  8. namespace: default
  9. spec:
  10. progressDeadlineSeconds: 600
  11. replicas: 2
  12. revisionHistoryLimit: 10
  13. selector:
  14. matchLabels:
  15. app: nginx
  16. strategy:
  17. rollingUpdate:
  18. maxSurge: 25%
  19. maxUnavailable: 25%
  20. type: RollingUpdate
  21. template:
  22. metadata:
  23. creationTimestamp: null
  24. labels:
  25. app: nginx
  26. spec:
  27. initContainers: #初始化操作部分
  28. - image: nginx
  29. imagePullPolicy: IfNotPresent
  30. command: ["sh", "-c", "echo InitContainer"]
  31. name: init1
  32. containers:
  33. - image: nginx
  34. imagePullPolicy: IfNotPresent
  35. name: nginx
  36. resources: {}
  37. terminationMessagePath: /dev/termination-log
  38. terminationMessagePolicy: File
  39. terminationMessagePath: /dev/termination-log
  40. terminationMessagePolicy: File
  41. volumeMounts:
  42. - mountPath: /opt
  43. name: share-volume
  44. - image: nginx
  45. imagePullPolicy: IfNotPresent
  46. name: nginx2
  47. command:
  48. - sh
  49. - -c
  50. - sleep 3600
  51. resources: {}
  52. terminationMessagePath: /dev/termination-log
  53. terminationMessagePolicy: File
  54. terminationMessagePath: /dev/termination-log
  55. terminationMessagePolicy: File
  56. volumeMounts:
  57. - mountPath: /mnt
  58. name: share-volume
  59. dnsPolicy: ClusterFirst
  60. restartPolicy: Always
  61. schedulerName: default-scheduler
  62. securityContext: {}
  63. terminationGracePeriodSeconds: 30
  64. volumes:
  65. - name: share-volume
  66. emptyDir: {}
  67. #medium: Memory

2.3 Affinity 亲和力

1.仍然存在的问题

Pod和节点之间的关系:

  • 某些Pod优先选择有ssd=true标签的节点,如果没有在考虑部署到其它节点;
  • 某些Pod需要部署在ssd=true和type=physical的节点上,但是优先部署在ssd=true的节点上;

Pod和Pod之间的关系:

  • 同一个应用的Pod不同的副本或者同一个项目的应用尽量或必须不部署在同一个节点或者符合某个标签的一类节点上或者不同的区域;
  • 相互依赖的两个Pod尽量或必须部署在同一个节点上或者同一个域内。

    2.Affinity亲和力分类

  • NodeAffinity:节点亲和力/反亲和力

    • ReqauiredDurinaSchedulinalanaredDuioqExesutiog:硬亲和力,即支持必须部署在指定的节点上,也支持必须不部署在指定的节点上。
    • PrefesredDuriogSchedulinalanoredDurinsExesution:软亲和力,尽量部署在满足条件的节点上,或者是尽量不要部署在被匹配的节点。
  • PodAffinity:Pod亲和力
  • A应用B应用C应用,将A应用根据某种策略尽量部署在一块。Label
    • ReqauiredDurinaSchedulinalanaredDuioqExesutiog
      • 将A应用和B应用部署在一块
    • PrefesredDuriogSchedulinalanoredDurinsExesution
      • 尽量将A应用和B应用部署在一块
        • Pod
        • tiAffinity:Pod反亲和力
  • A应用B应用C应用,将A应用根据某种策略尽量尽量或不部署在一块。Label
    • ReqauiredDurinaSchedulinalanaredDuioqExesutiog
      • 不要将A应用与之匹配的应用部署在一块
    • PrefesredDuriogSchedulinalanoredDurinsExesution
      • 尽量不要将A应用与之匹配的应用部署在一块

image.png

3.提高可用率—部署至不同宿主机

image.png
image.png

4.提高可用率—部署至不同机房/机柜

image.png
image.png

5.提高可用率—不放在同一个篮子里

image.png
image.png

6.NodeAffinity:节点亲和力

查看节点labels
kubectl get node --show-labels
给节点打上label
kubectl label nodes k8s-node02 kubernetes.io/e2e-az-name=e2e-az2
kubectl label nodes k8s-node03 kubernetes.io/e2e-az-name=e2e-az3
kubectl label nodes k8s-node02 another-node-label-key=another-node-label-value
kubectl label nodes k8s-master01 another-node-label-key=another-node-label-value

pod配置示例

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. annotations:
  5. deployment.kubernetes.io/revision: "2"
  6. creationTimestamp: "2022-03-27T04:03:07Z"
  7. generation: 2
  8. labels:
  9. app: nginx
  10. name: nginx
  11. namespace: default
  12. resourceVersion: "259372"
  13. uid: 6de3d5a5-9324-4ba4-870b-d964953fd263
  14. spec:
  15. progressDeadlineSeconds: 600
  16. replicas: 2
  17. revisionHistoryLimit: 10
  18. selector:
  19. matchLabels:
  20. app: nginx
  21. strategy:
  22. rollingUpdate:
  23. maxSurge: 25%
  24. maxUnavailable: 25%
  25. type: RollingUpdate
  26. template:
  27. metadata:
  28. creationTimestamp: null
  29. labels:
  30. app: nginx
  31. spec:
  32. affinity: #节点亲和力配置
  33. nodeAffinity:
  34. preferredDuringSchedulingIgnoredDuringExecution:
  35. - preference:
  36. matchExpressions:
  37. - key: another-node-label-key
  38. operator: In #满足多个条件的节点
  39. values:
  40. - another-node-label-value
  41. weight: 1
  42. requiredDuringSchedulingIgnoredDuringExecution:
  43. nodeSelectorTerms:
  44. - matchExpressions:
  45. - key: kubernetes.io/e2e-az-name
  46. operator: In
  47. values:
  48. - e2e-az2
  49. - e2e-az3
  50. #说明operator
  51. In 部署在满足多个条件的节点上
  52. NotIn 不部署在满足多个条件的节点上
  53. Exists 部署在具有某个存在的KEY为指定的值的node节点上
  54. DoesNotExist 不部署在具有某个存在的KEY为指定的值的node节点上
  55. Gt: 大于指定的条件 条件为number数字,不能为字符串
  56. Lt: 小于指定的条件 条件为number数字,不能为字符串
  57. containers:
  58. - image: nginx
  59. imagePullPolicy: IfNotPresent
  60. name: nginx
  61. resources: {}
  62. terminationMessagePath: /dev/termination-log
  63. terminationMessagePolicy: File
  64. volumeMounts:
  65. - mountPath: /opt
  66. name: share-volume
  67. - command:
  68. - sh
  69. - -c
  70. - sleep 3600
  71. image: nginx
  72. imagePullPolicy: IfNotPresent
  73. name: nginx2
  74. resources: {}
  75. terminationMessagePath: /dev/termination-log
  76. terminationMessagePolicy: File
  77. volumeMounts:
  78. - mountPath: /mnt
  79. name: share-volume
  80. dnsPolicy: ClusterFirst
  81. initContainers:
  82. - command:
  83. - sh
  84. - -c
  85. - echo InitContainer
  86. image: nginx
  87. imagePullPolicy: IfNotPresent
  88. name: init1
  89. resources: {}
  90. terminationMessagePath: /dev/termination-log
  91. terminationMessagePolicy: File
  92. restartPolicy: Always
  93. schedulerName: default-scheduler
  94. securityContext: {}
  95. terminationGracePeriodSeconds: 30
  96. volumes:
  97. - emptyDir: {}
  98. name: share-volume

查看nginx部署的节点

  1. root@k8s-master01:~/yaml# kubectl get pod -o wide
  2. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  3. nginx-748b86ff5c-hn8gw 2/2 Running 0 14m 172.27.14.215 k8s-node02 <none> <none>
  4. nginx-748b86ff5c-qgjb4 2/2 Running 0 14m 172.27.14.214 k8s-node02 <none> <none>

删除k8s-node2的label another-node-label-key
kubectl label nodes k8s-node02 another-node-label-key-

在看nginx部署的节点

  1. root@k8s-master01:~/yaml# kubectl get pod -o wide
  2. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  3. nginx-748b86ff5c-hn8gw 2/2 Running 0 16m 172.27.14.215 k8s-node02 <none> <none>
  4. nginx-748b86ff5c-qgjb4 2/2 Running 0 17m 172.27.14.214 k8s-node02 <none> <none>

可以看到还是在node02上,说明

  • ReqauiredDurinaSchedulinalanaredDuioqExesutiog:硬亲和力
  • PrefesredDuriogSchedulinalanoredDurinsExesution:软亲和力

硬亲和力和软亲和力是和的关系

7.pod亲和力和反亲和力

示例:

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. labels:
  5. app: nginx
  6. name: nginx-podAffinity
  7. namespace: default
  8. spec:
  9. progressDeadlineSeconds: 600
  10. replicas: 2
  11. revisionHistoryLimit: 10
  12. selector:
  13. matchLabels:
  14. app: nginx
  15. strategy:
  16. rollingUpdate:
  17. maxSurge: 25%
  18. maxUnavailable: 25%
  19. type: RollingUpdate
  20. template:
  21. metadata:
  22. creationTimestamp: null
  23. labels:
  24. app: nginx
  25. spec:
  26. #配置说明在下面
  27. demo-nginxkube-system namespaces下的符合labelk8s-app=calico-kube-controllerspod部署在同一个节点上
  28. affinity:
  29. podAffinity:
  30. requiredDuringSchedulingIgnoredDuringExecution:
  31. - labelSelector:
  32. matchExpressions:
  33. - key: k8s-app
  34. operator: In
  35. values:
  36. - calico-kube-controllers
  37. #如果写了namespaces 的字段,但是留空,他是匹配所有namespace 下的指定label的Pod,如果写了namespace并且指定了值,就是匹配指定namespace下的指定label的Pod。
  38. namespaces:
  39. - kube-system
  40. topologyKey: kubernetes.io/hostname 修改自己服务器上的key
  41. containers:
  42. - image: nginx:1.15.2
  43. imagePullPolicy: IfNotPresent
  44. name: nginx
  45. resources: {}
  46. terminationMessagePath: /dev/termination-log
  47. terminationMessagePolicy: File
  48. terminationMessagePath: /dev/termination-log
  49. terminationMessagePolicy: File
  50. volumeMounts:
  51. - mountPath: /opt
  52. name: share-volume
  53. - image: nginx:1.15.2
  54. imagePullPolicy: IfNotPresent
  55. name: nginx2
  56. command:
  57. - sh
  58. - -c
  59. - sleep 3600
  60. resources: {}
  61. terminationMessagePath: /dev/termination-log
  62. terminationMessagePolicy: File
  63. terminationMessagePath: /dev/termination-log
  64. terminationMessagePolicy: File
  65. volumeMounts:
  66. - mountPath: /mnt
  67. name: share-volume
  68. dnsPolicy: ClusterFirst
  69. restartPolicy: Always
  70. schedulerName: default-scheduler
  71. securityContext: {}
  72. terminationGracePeriodSeconds: 30
  73. volumes:
  74. - name: share-volume
  75. emptyDir: {}
  76. #medium: Memory

说明:

  • labelSelector:Pod选择器配置,可以配置多个
  • matchExpressions:和节点亲和力配置一致
  • operator:配置和节点亲和力一致,但是没有Gt和Lt
  • topologyKey:匹配的拓扑域的key,也就是节点上label的key,key和value相同的为同一个域,可以用于标注不同的机房和地区
  • namespaces 如果写了namespaces 的字段,但是留空,他是匹配所有namespace 下的指定label的Pod,如果写了namespace并且指定了值,就是匹配指定namespace下的指定label的Pod。

8. Topology拓扑域

1.什么是topology key

pod亲和性调度需要各个相关的pod对象运行于”同一位置”, 而反亲和性调度则要求他们不能运行于”同一位置”,

这里指定“同一位置” 是通过 topologyKey 来定义的,topologyKey 对应的值是 node 上的一个标签名称,比如各别节点zone=A标签,各别节点有zone=B标签,pod affinity topologyKey定义为zone,那么调度pod的时候就会围绕着A拓扑,B拓扑来调度,而相同拓扑下的node就为“同一位置”。

如果基于各个节点kubernetes.io/hostname标签作为评判标准,那么很明显“同一位置”意味着同一节点,不同节点既为不同位置,
一般用于:

  1. 我启动一个pod,希望(亲和性)或不希望(反亲和性)调度一台node上,并且这台node上有service=nginx标签的pod
  2. 我启动一个2个副本控制器,pod标签为service=tomcat,可以调度到任意node上,不希望两个pod调度到同一个node上

个人理解:pod affinity的调度范围为topology

官方解释:
如果该X已经在运行一个或多个满足规则Y的Pod,则该Pod应该(或者在非亲和性的情况下不应该)在X中运行
Y表示为LabelSelector规则
X是一个拓扑域,例如节点,机架,云提供者区域,云提供者区域等。您可以使用topologyKey这是系统用来表示这种拓扑域的节点标签的密钥

2.例子:

需求:当前有两个机房( beijing,shanghai),需要部署一个nginx产品,副本为两个,为了保证机房容灾高可用场景,需要在两个机房分别部署一个副本

  1. apiVersion: apps/v1
  2. kind: StatefulSet
  3. metadata:
  4. name: nginx-affinity-test
  5. spec:
  6. serviceName: nginx-service
  7. replicas: 2
  8. selector:
  9. matchLabels:
  10. service: nginx
  11. template:
  12. metadata:
  13. name: nginx
  14. labels:
  15. service: nginx
  16. spec:
  17. affinity:
  18. podAntiAffinity:
  19. requiredDuringSchedulingIgnoredDuringExecution:
  20. - labelSelector:
  21. matchExpressions:
  22. - key: service
  23. operator: In
  24. values:
  25. - nginx
  26. topologyKey: zone
  27. containers:
  28. - name: nginx
  29. image: contos7:latest
  30. command:
  31. - sleep
  32. - "360000000"

image.png

解释:两个node上分别有zone标签,来标注自己属于哪个机房,topologyKey定义为zone,pod所以在调度的时候,会根据node上zone标签来区分拓扑域,当前用的上 反亲和性调度 根据拓扑纬度调度,beijing机房调度完一个pod后,然后控制器判断beijing 拓扑域已经有server=nginx标签的pod,就在下一个拓扑域的node上调度了。

9,临时容器概念和配置

临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启, 因此不适用于构建应用程序。临时容器使用与常规容器相同的 ContainerSpec 节来描述,但许多字段是不兼容和不允许的。

  • 临时容器没有端口配置,因此像 ports,livenessProbe,readinessProbe 这样的字段是不允许的。
  • Pod 资源分配是不可变的,因此 resources 配置是不允许的。
  • 有关允许字段的完整列表,请参见 EphemeralContainer 参考文档。

临时容器是使用 API 中的一种特殊的 ephemeralcontainers 处理器进行创建的, 而不是直接添加到 pod.spec 段,因此无法使用 kubectl edit 来添加一个临时容器。
与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器。
使用临时容器需要开启 EphemeralContainers 特性门控, kubectl 版本为 v1.18 或者更高。

1.从镜像角度探讨容器安全

image.png

2.临时容器

image.png

3.开启临时容器

master节点上操作

修改apiserver
编辑/etc/kubernetes/manifests/kube-apiserver.yaml

将—feature-gates=TTLAfterFinished=true修改为—feature-gates=TTLAfterFinished=true,EphemeralContainers=true

修改controller-manager
编辑/etc/kubernetes/manifests/kube-controller-manager.yaml

将—feature-gates=TTLAfterFinished=true修改为—feature-gates=TTLAfterFinished=true,EphemeralContainers=true

修改kube-scheduler
编辑/etc/kubernetes/manifests/kube-scheduler.yaml

将—feature-gates=TTLAfterFinished=true修改为—feature-gates=TTLAfterFinished=true,EphemeralContainers=true

所以节点上操作

修改kubelet
编辑/var/lib/kubelet/kubeadm-flags.env
添加—feature-gates=EphemeralContainers=true

修改后如下
KUBELET_KUBEADM_ARGS=”—cgroup-driver=systemd —network-plugin=cni —pod-infra-container-image=k8s.gcr.io/pause:3.6 —feature-gates=EphemeralContainers=true”

重启kubelet
systemctl daemon-reload
systemctl restat kubelet

4.临时容器使用

官方文档 https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/
K8s 1.18+ kubectl alpha debug redis-new-5b577b46c7-2jv4j -ti --image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools
K8s 1.20+ kubectl debug redis-new-5b577b46c7-2jv4j -ti --image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools
kubectl debug node/k8s-node01 -it --image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools

参考文档:https://www.hebbao.com/1431.html
参考文档:https://blog.51cto.com/u_14848702/5055176
https://blog.csdn.net/chengyinwu/article/details/120867944
https://jishuin.proginn.com/p/763bfbd69bdc
http://114.115.155.37/2022/03/21/k8s-19/

3.高级准入控制

4.细粒度权限控制

API Server目前支持以下几种授权策略:

AlwaysDeny:表示拒绝所有请求,一般用于测试。
AlwaysAllow:允许接收所有请求。
如果集群不需要授权流程,则可以采用该策略,这也是Kubernetes的默认配置。
ABAC(Attribute-Based Access Control):基于属性的访问控制。
表示使用用户配置的授权规则对用户请求进行匹配和控制。
Webhook:通过调用外部REST服务对用户进行授权。
RBAC:Role-Based Access Control,基于角色的访问控制。
Node:是一种专用模式,用于对kubelet发出的请求进行访问控制。

1.RBAC权限管理概念

RBAC(Role-Based Access Control,基于角色的访问控制)是一种基于企业内个人用户的角色来管理对计算机或网络资源的访问方法,其在Kubernetes 1.5版本中引入,在1.6时升级为Beta版本,并成为Kubeadm安装方式下的默认选项。启用RBAC需要在启动APIServer时指定—authorization-mode=RBAC。

RBAC使用rbac.authorization.k8s.io API组来推动授权决策,允许管理员通过Kubernetes API动态配置策略。

RBAC API声明了4种顶级资源对象,即Role、ClusterRole、RoleBinding、ClusterRoleBinding,管理员可以像使用其他API资源一样使用kubectl API调用这些资源对象。例如:kubectl create -f (resource).yml。

授权介绍

在RABC API中,通过如下的步骤进行授权:

  • 定义角色:在定义角色时会指定此角色对于资源的访问控制的规则。
  • 绑定角色:将主体与角色进行绑定,对用户进行访问授权。

角色

  • Role:授权特定命名空间的访问权限
  • ClusterRole:授权所有命名空间的访问权限
  • Role和ClusterRole的关键区别是,Role是作用于命名空间内的角色,ClusterRole作用于整个集群的角色。
  • 在RBAC API中,Role包含表示一组权限的规则。权限纯粹是附加允许的,没有拒绝规则。Role只能授权对单个命名空间内的资源的访问权限,比如授权对default命名空间的读取权限
  • ClusterRole也可将上述权限授予作用于整个集群的Role,主要区别是,ClusterRole是集群范围的,因此它们还可以授予对以下内容的访问权限:
    • l 集群范围的资源(如Node)。
    • 非资源端点(如/healthz)。
    • 跨所有命名空间的命名空间资源(如Pod)。

角色绑定

  • RoleBinding:将角色绑定到主体(即subject)
  • ClusterRoleBinding:将集群角色绑定到主体
  • RoleBinding将Role中定义的权限授予User、Group或Service Account。RoleBinding和ClusterRoleBinding最大的区别与Role和ClusterRole的区别类似,即RoleBinding作用于命名空间,ClusterRoleBinding作用于集群。
  • RoleBinding可以引用同一命名空间的Role进行授权,比如将上述创建的pod-reader的Role授予default命名空间的用户jane,这将允许jane读取default命名空间中的Pod
  • RoleBinding也可以引用ClusterRole来授予对命名空间资源的某些权限。管理员可以为整个集群定义一组公用的ClusterRole,然后在多个命名空间中重复使用。
  • ClusterRoleBinding可用于在集群级别和所有命名空间中授予权限,比如允许组manager中的所有用户都能读取任何命名空间的Secret:

主体(subject)

  • User:用户
  • Group:用户组
  • ServiceAccount:服务账号

四、K8S高级篇

1.云原生存储及存储进阶

2.中间件容器化及Helm

五、K8S运维篇