通过ECS公网IP部署K8S集群,持续更新,敬请期待...

节点规划

部署k8s集群的节点按照用途可以划分为如下2类角色:

  • master:集群的master节点,集群的初始化节点,基础配置不低于2C4G
  • slave:集群的slave节点,可以多台,基础配置不低于2C4G

本例为了演示slave节点的添加,会部署一台master+2台slave,节点规划如下:

主机名节点ip角色部署组件
k8s-masterxxx.xxx.xxx.xxmasteretcd, kube-apiserver, kube-controller-manager, kubectl, kubeadm, kubelet, kube-proxy, flannel
k8s-slave1xxx.xxx.xxx.xxslavekubectl, kubelet, kube-proxy, flannel
k8s-slave2xxx.xxx.xxx.xxslavekubectl, kubelet, kube-proxy, flannel

组件版本

组件版本说明
CentOS7.8.2003
KernelLinux 3.10.0-1127.10.1.el7.x86_64
etcd3.4.13-0使用Pod方式部署,默认数据挂载到本地路径
coredns1.7.0
kubeadmv1.21.5
kubectlv1.21.5
kubeletv1.21.5
kube-proxyv1.21.5
flannelv0.19.2

设置hosts解析

操作节点:所有节点(k8s-master,k8s-slave)均需执行

  • 修改hostname hostname必须只能包含小写字母、数字、","、"-",且开头结尾必须是小写字母或数字
# 在master节点
$ hostnamectl set-hostname k8s-master #设置master节点的hostname

# 在slave-1节点
$ hostnamectl set-hostname k8s-slave1 #设置slave1节点的hostname

# 在slave-2节点
$ hostnamectl set-hostname k8s-slave2 #设置slave2节点的hostname
  • 添加hosts解析
$ cat >>/etc/hosts<<EOF
xxx.xxx.xxx.xxx k8s-master
xxx.xxx.xxx.xxx k8s-slave1
xxx.xxx.xxx.xxx k8s-slave2
EOF

调整系统配置

操作节点: 所有的master和slave节点(k8s-master,k8s-slave)需要执行

本章下述操作均以k8s-master为例,其他节点均是相同的操作(ip和hostname的值换成对应机器的真实值)

  • 设置安全组开放端口

如果节点间无安全组限制(内网机器间可以任意访问),可以忽略,否则,至少保证如下端口可通: k8s-master节点:TCP:6443,2379,2380,60080,60081UDP协议端口全部打开 k8s-slave节点:UDP协议端口全部打开

  • 设置iptables
iptables -P FORWARD ACCEPT
  • 关闭swap
swapoff -a
# 防止开机自动挂载 swap 分区
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
  • 关闭selinux和防火墙
sed -ri 's#(SELINUX=).*#\1disabled#' /etc/selinux/config
setenforce 0
systemctl disable firewalld && systemctl stop firewalld
  • 修改内核参数
cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
vm.max_map_count=262144
EOF
modprobe br_netfilter
sysctl -p /etc/sysctl.d/k8s.conf
  • 设置yum源
$ curl -o /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
$ curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
$ cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
        http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
$ yum clean all && yum makecache

安装docker

操作节点: 所有节点

 ## 查看所有的可用版本
$ yum list docker-ce --showduplicates | sort -r
##安装旧版本 yum install docker-ce-cli-18.09.9-3.el7  docker-ce-18.09.9-3.el7
## 安装源里最新版本
$ yum install docker-ce-20.10.18 -y

## 配置docker加速和非安全的镜像仓库,需要根据个人的实际环境修改
$ mkdir -p /etc/docker
vi /etc/docker/daemon.json
{
  "insecure-registries": [    
    "xxx.xxx.xxx.xxxx:5000"  #公网ip地址 
  ],                          
  "registry-mirrors" : [
    "https://8xpk5wnt.mirror.aliyuncs.com"
  ]
}
## 启动docker
$ systemctl enable docker && systemctl start docker

安装 kubeadm, kubelet 和 kubectl

操作节点: 所有的master和slave节点(k8s-master,k8s-slave) 需要执行

$ yum install -y kubelet-1.24.4 kubeadm-1.24.4 kubectl-1.24.4 --disableexcludes=kubernetes
## 查看kubeadm 版本
$ kubeadm version
## 设置kubelet开机启动
$ systemctl enable kubelet 

配置containerd

操作节点:所有的master和slave节点(k8s-master,k8s-slave) 需要执行

  • 将 sandbox_image 镜像源设置为阿里云google_containers镜像源:

    # 导出默认配置,config.toml这个文件默认是不存在的
    containerd config default > /etc/containerd/config.toml
    grep sandbox_image  /etc/containerd/config.toml
    sed -i "s#k8s.gcr.io/pause#registry.aliyuncs.com/google_containers/pause#g"       /etc/containerd/config.toml
    sed -i "s#registry.k8s.io/pause#registry.aliyuncs.com/google_containers/pause#g"       /etc/containerd/config.toml
  • 配置containerd cgroup 驱动程序systemd:

    sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml
  • 配置docker hub镜像加速:

    # 修改配置文件/etc/containerd/config.toml, 145行添加config_path
    ...
        144     [plugins."io.containerd.grpc.v1.cri".registry]
        145       config_path = "/etc/containerd/certs.d"
        146
        147       [plugins."io.containerd.grpc.v1.cri".registry.auths]
        148
        149       [plugins."io.containerd.grpc.v1.cri".registry.configs]
        150
        151       [plugins."io.containerd.grpc.v1.cri".registry.headers]
        152
        153       [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    ...
    
    # 创建对应的目录
    mkdir -p /etc/containerd/certs.d/docker.io
    
    # 配置加速
    cat >/etc/containerd/certs.d/docker.io/hosts.toml <<EOF
    server = "https://docker.io"
    [host."https://8xpk5wnt.mirror.aliyuncs.com"]
      capabilities = ["pull","resolve"]
    [host."https://docker.mirrors.ustc.edu.cn"]
      capabilities = ["pull","resolve"]
    [host."https://registry-1.docker.io"]
      capabilities = ["pull","resolve","push"]
    EOF
  • 配置非安全的私有镜像仓库:

    # 此处目录必须和个人环境中实际的仓库地址保持一致
    mkdir -p /etc/containerd/certs.d/172.21.65.226:5000
    cat >/etc/containerd/certs.d/172.21.65.226:5000/hosts.toml <<EOF
    server = "http://172.21.65.226:5000"
    [host."http://172.21.65.226:5000"]
      capabilities = ["pull", "resolve", "push"]
      skip_verify = true
    EOF
  • 应用所有更改后,重新启动containerd:

    systemctl restart containerd

初始化配置文件

操作节点: 只在master节点(k8s-master)执行

$ kubeadm config print init-defaults > kubeadm.yaml
$ cat kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: xxx.xxx.xxx.xxx   # 此处替换为k8s-master的公网ip地址
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///var/run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  name: k8s-master                    # 此处替换为k8s-master的hostname
  taints: null
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers   # 替换为国内镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.24.4              # 替换为1.24.4
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16              # 添加此行,用来分配k8s节点的pod ip
  serviceSubnet: 10.96.0.0/12
scheduler: {}

对于上面的资源清单的文档比较杂,要想完整了解上面的资源对象对应的属性,可以查看对应的 godoc 文档,地址: https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3。

提前下载镜像

操作节点:只在master节点(k8s-master)执行

  # 查看需要使用的镜像列表,若无问题,将得到如下列表
$ kubeadm config images list --config kubeadm.yaml
registry.aliyuncs.com/google_containers/kube-apiserver:v1.24.4
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.24.4
registry.aliyuncs.com/google_containers/kube-scheduler:v1.24.4
registry.aliyuncs.com/google_containers/kube-proxy:v1.24.4
registry.aliyuncs.com/google_containers/pause:3.7
registry.aliyuncs.com/google_containers/etcd:3.5.3-0
registry.aliyuncs.com/google_containers/coredns:v1.8.6
  # 提前下载镜像到本地
$ kubeadm config images pull --config kubeadm.yaml
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.24.4
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.24.4
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.24.4
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.24.4
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.7
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.5.3-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:v1.8.6

初始化master节点

操作节点:只在master节点(k8s-master)执行,注意只在master节点执行!

$ kubeadm init --config kubeadm.yaml

 第一次执行报错

 查询资料后问题发现解决阿里云ECS下kubeadm部署k8s无法指定公网IP(作废) - LifeOfCoding - 博客园 (cnblogs.com)

解决问题

  • 首先将生成的/etc/kubernetes/manifests/etcd.yaml文件进行修改
       [root@k8s-master /etc/kubernetes/manifests]# vim etcd.yaml
        - --listen-client-urls=https://0.0.0.0:2379
        - --listen-peer-urls=https://0.0.0.0:2380
    

    进行保存。

  • 清除配置

    [root@k8s-master ~/k8s]# kubeadm  reset
    
  • 重新初始化

    [root@k8s-master ~/k8s]# kubeadm  init --config kubeadm.yaml --ignore-preflight-errors=FileAvailable--etc-kubernetes-manifests-etcd.yaml --v=7

            此参数将指示 kubeadm 忽略因为 etcd 配置文件已存在而引发的前置检查错误。这将允许初始化过程继续进行而不会覆盖现有的 etcd.yaml 文件。

            然而,请注意,忽略前置检查错误并继续进行可能涉及一定的风险。在忽略错误前,确保您完全理解为何存在该文件以及它的内容是否正确配置。如果该文件为由于以前未完成的初始化过程而遗留下来的,那么它可能不包含正确的配置,继续使用可能会导致集群初始化不正确或运行不稳定。

            因此,在忽略这种错误之前,应当进行以下检查确保了解该文件的目的和内容。检查集群的当前状态,确认是否真的可以继续使用现有的 etcd 配置。特别是在生产环境中操作时,保持谨慎是非常重要的,因为对集群如果您已经存在 /etc/kubernetes/manifests/etcd.yaml 文件,并且不希望在运行 kubeadm init 时该文件被替换或改动,那么使用 --ignore-preflight-errors 参数来忽略这个具体的错误是可行的。这个参数将会告诉 kubeadm init 忽略检查到该文件已存在的这一错误,并继续执行初始化流程。确保有足够的备份,以防忽略这个错误后导致未预见的问题。如果不确定文件的准确性,或者是第一次初始化集群,建议备份然后移除该文件,让 kubeadm init 生成新的配置。如果您需要忽略多个错误,可以使用逗号分隔各个错误名称,例如:kubeadm init --ignore-preflight-errors=FileAvailable--etc-kubernetes-manifests-etcd.yaml,SomeOtherError

  • 执行成功

接下来按照上述提示信息操作,配置kubectl客户端的认证,并将master节点的admin.conf拷贝至所有salve节点

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

⚠️注意:此时使用 kubectl get nodes查看节点应该处于notReady状态,因为还未配置网络插件

若执行初始化过程中出错,根据错误信息调整后,执行kubeadm reset后再次执行init操作即可

添加slave节点到集群中

操作节点:所有的slave节点(k8s-slave)需要执行 在每台slave节点,执行如下命令,该命令是在kubeadm init成功后提示信息中打印出来的,需要替换成实际init后打印出的命令。

kubeadm join xxx.xxxx.xxx.xxxx:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:1c4305f032f4bf534f628c32f5039084f4b103c922ff71b12a5f0f98d1ca9a4f

如果忘记添加命令,可以通过如下命令生成:

$ kubeadm token create --print-join-command

操作节点:只在master节点(k8s-master)执行,CNI

  • 下载flannel的yaml文件

    wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
  • 修改配置,指定网卡名称,大概在文件的172行,添加一行配置:

    $ vi kube-flannel.yml
    ...      
    150       containers:
    151       - name: kube-flannel
    152        #image: flannelcni/flannel:v0.19.2 for ppc64le and mips64le (dockerhub limitations may apply)
    153         image: docker.io/rancher/mirrored-flannelcni-flannel:v0.19.2
    154         command:
    155         - /opt/bin/flanneld
    156         args:
    157         - --ip-masq
    158         - --kube-subnet-mgr
    159         - --iface=eth0   # 如果机器存在多网卡的话,指定内网网卡的名称,默认不指定的话会找第一块网卡
    160         resources:
    161           requests:
    162             cpu: "100m"
    163             memory: "50Mi"
    ...
  • 确认pod网段

    vi kube-flannel.yml
         98   net-conf.json: |
         99     {
        100       "Network": "10.244.0.0/16",
        101       "Backend": {
        102         "Type": "vxlan"
        103       }
        104     }
     
    # 确认84行的网段和前面kubeadm.yaml中初始化使用的配置中的podSubnet保持一致!
  • 执行安装flannel网络插件

    # 执行flannel安装
    kubectl apply -f kube-flannel.yml
    kubectl -n kube-flannel get po -owide

       

  • node节点查询
  •  flannel网络查询

设置master节点是否可调度(可选)

操作节点:k8s-master

默认部署成功后,master节点无法调度业务pod,如需设置master节点也可以参与pod的调度,需执行:

kubectl taint node k8s-master node-role.kubernetes.io/master:NoSchedule-
kubectl taint node k8s-master node-role.kubernetes.io/control-plane:NoSchedule-

课程后期会部署系统组件到master节点,因此,此处建议设置k8s-master节点为可调度

设置kubectl自动补全

操作节点:k8s-master

$ yum install bash-completion -y
$ source /usr/share/bash-completion/bash_completion
$ source <(kubectl completion bash)
$ echo "source <(kubectl completion bash)" >> ~/.bashrc

使用kubeadm安装的集群,证书默认有效期为1年,可以通过如下方式修改为10年。

cd /etc/kubernetes/pki

# 查看当前证书有效期
for i in $(ls *.crt); do echo "===== $i ====="; openssl x509 -in $i -text -noout | grep -A 3 'Validity' ; done

 有效期1年

 拉取证书

[root@k8s-master /etc/kubernetes/pki]# git clone https://github.com/yuyicai/update-kube-cert.git
正克隆到 'update-kube-cert'...
remote: Enumerating objects: 140, done.
remote: Counting objects: 100% (28/28), done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 140 (delta 4), reused 6 (delta 3), pack-reused 112
接收对象中: 100% (140/140), 46.89 KiB | 0 bytes/s, done.
处理 delta 中: 100% (67/67), done.

进入目录执行

[root@k8s-master /etc/kubernetes/pki]# cd update-kube-cert/
[root@k8s-master /etc/kubernetes/pki/update-kube-cert]# ll
总用量 60
-rw-r--r-- 1 root root  1064 12月  3 13:34 LICENSE
-rw-r--r-- 1 root root  2760 12月  3 13:34 other.md
-rw-r--r-- 1 root root  2322 12月  3 13:34 other-zh_CN.md
-rw-r--r-- 1 root root  7318 12月  3 13:34 README.md
-rw-r--r-- 1 root root  7228 12月  3 13:34 README-zh_CN.md
-rw-r--r-- 1 root root 13285 12月  3 13:34 update-kubeadm-cert-crictl.sh
-rwxr-xr-x 1 root root 13068 12月  3 13:34 update-kubeadm-cert.sh
[root@k8s-master /etc/kubernetes/pki/update-kube-cert]# bash update-kubeadm-cert.sh all
CERTIFICATE                                       EXPIRES
/etc/kubernetes/controller-manager.config         Dec  2 03:47:48 2024 GMT
/etc/kubernetes/scheduler.config                  Dec  2 03:47:49 2024 GMT
/etc/kubernetes/admin.config                      Dec  2 03:47:47 2024 GMT
/etc/kubernetes/pki/ca.crt                        Nov 30 03:47:40 2033 GMT
/etc/kubernetes/pki/apiserver.crt                 Dec  2 03:47:41 2024 GMT
/etc/kubernetes/pki/apiserver-kubelet-client.crt  Dec  2 03:47:42 2024 GMT
/etc/kubernetes/pki/front-proxy-ca.crt            Nov 30 03:47:42 2033 GMT
/etc/kubernetes/pki/front-proxy-client.crt        Dec  2 03:47:43 2024 GMT
/etc/kubernetes/pki/etcd/ca.crt                   Nov 30 03:47:44 2033 GMT
/etc/kubernetes/pki/etcd/server.crt               Dec  2 03:47:44 2024 GMT
/etc/kubernetes/pki/etcd/peer.crt                 Dec  2 03:47:44 2024 GMT
/etc/kubernetes/pki/etcd/healthcheck-client.crt   Dec  2 03:47:46 2024 GMT
/etc/kubernetes/pki/apiserver-etcd-client.crt     Dec  2 03:47:46 2024 GMT
[2023-12-03T13:35:43.08+0800][INFO] backup /etc/kubernetes to /etc/kubernetes.old-20231203
[2023-12-03T13:35:43.09+0800][INFO] updating...
[2023-12-03T13:35:43.28+0800][INFO] updated /etc/kubernetes/pki/etcd/server.conf
[2023-12-03T13:35:43.46+0800][INFO] updated /etc/kubernetes/pki/etcd/peer.conf
[2023-12-03T13:35:43.58+0800][INFO] updated /etc/kubernetes/pki/etcd/healthcheck-client.conf
[2023-12-03T13:35:43.72+0800][INFO] updated /etc/kubernetes/pki/apiserver-etcd-client.conf
[2023-12-03T13:35:44.50+0800][INFO] restarted etcd
[2023-12-03T13:35:44.75+0800][INFO] updated /etc/kubernetes/pki/apiserver.crt
[2023-12-03T13:35:44.90+0800][INFO] updated /etc/kubernetes/pki/apiserver-kubelet-client.crt
[2023-12-03T13:35:45.10+0800][INFO] updated /etc/kubernetes/controller-manager.conf
[2023-12-03T13:35:45.26+0800][INFO] updated /etc/kubernetes/scheduler.conf
[2023-12-03T13:35:45.45+0800][INFO] updated /etc/kubernetes/admin.conf
[2023-12-03T13:35:45.47+0800][INFO] backup /root/.kube/config to /root/.kube/config.old-20231203
[2023-12-03T13:35:45.48+0800][INFO] copy the admin.conf to /root/.kube/config
[2023-12-03T13:35:45.48+0800][INFO] does not need to update kubelet.conf
[2023-12-03T13:35:45.69+0800][INFO] updated /etc/kubernetes/pki/front-proxy-client.crt
[2023-12-03T13:35:57.05+0800][INFO] restarted apiserver
[2023-12-03T13:35:57.93+0800][INFO] restarted controller-manager
[2023-12-03T13:35:58.92+0800][INFO] restarted scheduler
[2023-12-03T13:35:59.19+0800][INFO] restarted kubelet
[2023-12-03T13:35:59.20+0800][INFO] done!!!
CERTIFICATE                                       EXPIRES
/etc/kubernetes/controller-manager.config         Nov 30 05:35:45 2033 GMT
/etc/kubernetes/scheduler.config                  Nov 30 05:35:45 2033 GMT
/etc/kubernetes/admin.config                      Nov 30 05:35:45 2033 GMT
/etc/kubernetes/pki/ca.crt                        Nov 30 03:47:40 2033 GMT
/etc/kubernetes/pki/apiserver.crt                 Nov 30 05:35:44 2033 GMT
/etc/kubernetes/pki/apiserver-kubelet-client.crt  Nov 30 05:35:44 2033 GMT
/etc/kubernetes/pki/front-proxy-ca.crt            Nov 30 03:47:42 2033 GMT
/etc/kubernetes/pki/front-proxy-client.crt        Nov 30 05:35:45 2033 GMT
/etc/kubernetes/pki/etcd/ca.crt                   Nov 30 03:47:44 2033 GMT
/etc/kubernetes/pki/etcd/server.crt               Nov 30 05:35:43 2033 GMT
/etc/kubernetes/pki/etcd/peer.crt                 Nov 30 05:35:43 2033 GMT
/etc/kubernetes/pki/etcd/healthcheck-client.crt   Nov 30 05:35:43 2033 GMT
/etc/kubernetes/pki/apiserver-etcd-client.crt     Nov 30 05:35:43 2033 GMT

再次查询有效期为10年

 集群验证

操作节点: 在master节点(k8s-master)执行

$ kubectl get nodes  #观察集群节点是否全部Ready

创建测试nginx服务

$ kubectl run  test-nginx --image=nginx:alpine

查看pod是否创建成功,并访问pod ip测试是否可用

$ kubectl get po -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
test-nginx-5bd8859b98-5nnnw   1/1     Running   0          9s    10.244.1.2   k8s-slave1   <none>           <none>
$ curl 10.244.1.2
...
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

第二章

本章学习kubernetes的架构及工作流程,重点介绍如何使用Workload管理业务应用的生命周期,实现服务不中断的滚动更新,通过服务发现和集群内负载均衡来实现集群内部的服务间访问,并通过ingress实现外部使用域名访问集群内部的服务。

学习过程中会逐步对容器项目做k8s改造,从零开始编写所需的资源文件。通过本章的学习,学员会掌握高可用k8s集群的搭建,同时容器项目已经可以利用k8s的控制器、服务发现、负载均衡、配置管理等特性来实现生命周期的管理。

纯容器模式的问题
  1. 业务容器数量庞大,哪些容器部署在哪些节点,使用了哪些端口,如何记录、管理,需要登录到每台机器去管理?
  2. 跨主机通信,多个机器中的容器之间相互调用如何做,iptables规则手动维护?
  3. 跨主机容器间互相调用,配置如何写?写死固定IP+端口?
  4. 如何实现业务高可用?多个容器对外提供服务如何实现负载均衡?
  5. 容器的业务中断了,如何可以感知到,感知到以后,如何自动启动新的容器?
  6. 如何实现滚动升级保证业务的连续性?
  7. ......
容器调度管理平台
  • Docker Swarm
  • Mesos
  • Google Kubernetes

2017年开始Kubernetes凭借强大的容器集群管理功能, 逐步占据市场,目前在容器编排领域一枝独秀

Kubernetes

架构图

如何设计一个容器管理平台?

  • 集群架构,管理节点分发容器到数据节点
  • 如何部署业务容器到各数据节点
  • N个数据节点,业务容器如何选择部署在最合理的节点
  • 容器如何实现多副本,如何满足每个机器部署一个容器的模型
  • 多副本如何实现集群内负载均衡

分布式系统,两类角色:管理节点和工作节点

核心组件
  • ETCD:分布式高性能键值数据库,存储整个集群的所有元数据

  • ApiServer: API服务器,集群资源访问控制入口,提供restAPI及安全访问控制

  • Scheduler:调度器,负责把业务容器调度到最合适的Node节点

  • Controller Manager:控制器管理,确保集群资源按照期望的方式运行

    • Replication Controller
    • Node controller
    • ResourceQuota Controller
    • Namespace Controller
    • ServiceAccount Controller
    • Token Controller
    • Service Controller
    • Endpoints Controller
  • kubelet:运行在每个节点上的主要的“节点代理”,脏活累活

    • pod 管理:kubelet 定期从所监听的数据源获取节点上 pod/container 的期望状态(运行什么容器、运行的副本数量、网络或者存储如何配置等等),并调用对应的容器平台接口达到这个状态。
    • 容器健康检查:kubelet 创建了容器之后还要查看容器是否正常运行,如果容器运行出错,就要根据 pod 设置的重启策略进行处理.
    • 容器监控:kubelet 会监控所在节点的资源使用情况,并定时向 master 报告,资源使用数据都是通过 cAdvisor 获取的。知道整个集群所有节点的资源情况,对于 pod 的调度和正常运行至关重要
  • kube-proxy:维护节点中的iptables或者ipvs规则

  • kubectl: 命令行接口,用于对 Kubernetes 集群运行命令 命令行工具 (kubectl) | Kubernetes

静态Pod的方式:

## etcd、apiserver、controller-manager、kube-scheduler
$ kubectl -n kube-system get po

systemd服务方式:

$ systemctl status kubelet

kubectl:二进制命令行工具

理解集群资源

组件是为了支撑k8s平台的运行,安装好的软件。

资源是如何去使用k8s的能力的定义。比如,k8s可以使用Pod来管理业务应用,那么Pod就是k8s集群中的一类资源,集群中的所有资源可以提供如下方式查看:

$ kubectl api-resources

如何理解namespace:

命名空间,集群内一个虚拟的概念,类似于资源池的概念,一个池子里可以有各种资源类型,绝大多数的资源都必须属于某一个namespace。集群初始化安装好之后,会默认有如下几个namespace:

$ kubectl get namespaces
NAME                   STATUS   AGE
default                Active   84m
kube-node-lease        Active   84m
kube-public            Active   84m
kube-system            Active   84m
kubernetes-dashboard   Active   71m
  • 所有NAMESPACED的资源,在创建的时候都需要指定namespace,若不指定,默认会在default命名空间下
  • 相同namespace下的同类资源不可以重名,不同类型的资源可以重名
  • 不同namespace下的同类资源可以重名
  • 通常在项目使用的时候,我们会创建带有业务含义的namespace来做逻辑上的整合

kubectl的使用

类似于docker,kubectl是命令行工具,用于与APIServer交互,内置了丰富的子命令,功能极其强大。 Command line tool (kubectl) | Kubernetes

$ kubectl -h
$ kubectl get -h
$ kubectl create -h
$ kubectl create namespace -h

 

最小调度单元 Pod

docker调度的是容器,在k8s集群中,最小的调度单元是Pod(豆荚)

为什么引入Pod
  • 与容器引擎解耦

    Docker、Rkt。平台设计与引擎的具体的实现解耦

  • 多容器共享网络|存储|进程 空间, 支持的业务场景更加灵活

Pod在集群中的形态

使用yaml格式定义Pod

pod-eladmin-api.yaml

apiVersion: v1
kind: Pod
metadata:
  name: eladmin-api
  namespace: luffy
  labels:
    app: eladmin-api
spec:
  containers:
  - name: eladmin-api
    image: xx.xxx.xxx.xxx:5000/eladmin/eladmin-api:v1
    env:
    - name: DB_HOST   #  指定数据库地址
      value: "xx.xxx.xxx.xxx"
    - name: DB_USER   #  指定数据库连接使用的用户
      value: "root"
    - name: DB_PWD
      value: "luffyAdmin!"
    - name: REDIS_HOST
      value: "xx.xxx.xxx.xxx"
    - name: REDIS_PORT
      value: "6379"
    ports:
    - containerPort: 8000
# http://www.wetools.com/yaml/
{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "name": "eladmin-api",
        "namespace": "luffy",
        "labels": {
            "app": "eladmin-api"
        }
    },
    "spec": {
        "containers": [
            {
                "name": "eladmin-api",
                "image": "xx.xxx.xxx.xxx:5000/eladmin/eladmin-api:v1",
                "env": [
                    {
                        "name": "DB_HOST",
                        "value": "xx.xxx.xxx.xxx"
                    },
                    {
                        "name": "DB_USER",
                        "value": "root"
                    },
                    {
                        "name": "DB_PWD",
                        "value": "luffyAdmin!"
                    },
                    {
                        "name": "REDIS_HOST",
                        "value": "xx.xxx.xxx.xxx"
                    },
                    {
                        "name": "REDIS_PORT",
                        "value": "6379"
                    }
                ],
                "ports": [
                    {
                        "containerPort": 8000
                    }
                ]
            }
        ]
    }
}
apiVersion含义
alpha进入K8s功能的早期候选版本,可能包含Bug,最终不一定进入K8s
beta已经过测试的版本,最终会进入K8s,但功能、对象定义可能会发生变更。
stable可安全使用的稳定版本
v1stable 版本之后的首个版本,包含了更多的核心对象
apps/v1使用最广泛的版本,像Deployment、ReplicaSets都已进入该版本

支持的资源类型与apiVersion

kubectl api-resources

快速获得资源和版本

$ kubectl explain pod
$ kubectl explain Pod.apiVersion
创建和访问Pod
## 创建namespace, namespace是逻辑上的资源池
kubectl create namespace luffy

## 使用指定文件创建Pod
kubectl create -f pod-eladmin-api.yaml


## ImagePullBackOff,创建镜像拉取所用的密钥信息
kubectl -n luffy create secret docker-registry registry-172-21-65-226 --docker-username=admin --docker-password=admin --docker-email=admin@admin.com --docker-server=172.21.65.226:5000

## 给pod配置上述密钥
apiVersion: v1
kind: Pod
metadata:
  name: eladmin-api
  namespace: luffy
  labels:
    app: eladmin-api
spec:
  imagePullSecrets:
  - name: registry-172-21-65-22
  containers:
  - name: eladmin-api
...

## 删除pod重建,两种方式
kubectl -n luffy delete pod eladmin-api
kubectl delete -f pod-eladmin-api.yaml



## 查看pod,可以简写po
## 所有的操作都需要指定namespace,如果是在default命名空间下,则可以省略
$ kubectl -n luffy get pods -o wide
NAME     READY   STATUS    RESTARTS   AGE    IP             NODE
eladmin-api   1/1     Running   0     11m   10.244.1.15   k8s-slave1 

## 回顾流程

## 使用Pod Ip访问服务,3306和8002
$ curl 10.244.1.15:8000/auth/code

## 进入容器,执行初始化, 不必到对应的主机执行docker exec
$ kubectl -n luffy exec -ti eladmin-api bash
/ # env
Infra容器

登录k8s-slave1节点


$ nerdctl -n k8s.io ps -a|grep eladmin-api  ## 发现有二个容器
## 其中包含eladmin容器以及pause容器
## 为了实现Pod内部的容器可以通过localhost通信,每个Pod都会启动pause容器,然后Pod内部的其他容器的网络空间会共享该pause容器的网络空间(Docker网络的container模式),pause容器只需要hang住网络空间,不需要额外的功能,因此资源消耗极低。



$ crictl  -r "unix:///var/run/containerd/containerd.sock" pull 172.21.65.226:5000/eladmin/eladmin-api:v1
$ crictl  -r "unix:///var/run/containerd/containerd.sock" rmi xxxxx
$ nerdctl pull 172.21.65.226:5000/eladmin/eladmin-api:v1
$ crictl -r "unix:///var/run/containerd/containerd.sock" logs -f 5627a65b98416
查看pod详细信息
## 查看pod调度节点及pod_ip
$ kubectl -n luffy get pods -o wide
## 查看完整的yaml
$ kubectl -n luffy get po eladmin-api -o yaml
## 查看pod的明细信息及事件
$ kubectl -n luffy describe pod eladmin-api
Troubleshooting and Debugging
#进入Pod内的容器
$ kubectl -n <namespace> exec <pod_name> -c <container_name> -ti /bin/sh

#查看Pod内容器日志,显示标准或者错误输出日志
$ kubectl -n <namespace> logs -f <pod_name> -c <container_name>
更新服务版本
$ kubectl apply -f pod-eladmin-api.yaml
删除Pod服务
#根据文件删除
$ kubectl delete -f pod-eladmin-api.yaml

#根据pod_name删除
$ kubectl -n <namespace> delete pod <pod_name>
Pod多容器

pod-eladmin.yaml

apiVersion: v1
kind: Pod
metadata:
  name: eladmin
  namespace: luffy
  labels:
    app: eladmin
spec:
  imagePullSecrets:
  - name: registry-172-21-65-226
  containers:
  - name: eladmin-api
    image: 172.21.65.226:5000/eladmin/eladmin-api:v1
    env:
    - name: DB_HOST   #  指定数据库地址
      value: "172.21.65.226"
    - name: DB_USER   #  指定数据库连接使用的用户
      value: "root"
    - name: DB_PWD
      value: "luffyAdmin!"
    - name: REDIS_HOST
      value: "172.21.65.226"
    - name: REDIS_PORT
      value: "6379"
    ports:
    - containerPort: 8000
  - name: eladmin-web
    image: 172.21.65.226:5000/eladmin/eladmin-web:v1
    ports:
    - containerPort: 80
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值