Kubernetes 深入学习


目录

  • 一、简介
    • 1、Kubernetes 是什么
    • 2、Kubernetes 特性
  • 二、集群架构与组件
    • 1、Master
    • 2、Node
  • 三、核心概念
  • 四、集群搭建 —— 平台规划
    • 1、生产环境 K8S 平台规划
    • 2、操作系统初始化
  • 五、集群搭建 —— 部署Etcd集群
    • 1、自签证书
    • 2、自签 Etcd SSL 证书
    • 3、Etcd 数据库集群部署
  • 六、集群搭建 —— 部署Master组件
    • 1、自签 ApiServer SSL 证书
    • 2、部署 kube-apiserver 组件
    • 3、部署 kube-controller-manager 组件
    • 4、部署 kube-scheduler 组件
    • 5、查看集群状态
  • 七、集群搭建 —— 部署Node组件
    • 1、安装 Docker
    • 2、Node 节点证书
    • 3、安装 kubelet
    • 4、安装 kube-proxy
    • 5、部署其它Node节点
    • 6、部署K8S容器集群网络(Flannel)
    • 7、部署内部 DNS 服务
  • 八、集群搭建 —— 部署 Dashboard
    • 1、部署 K8S Dashboard
    • 2、登录授权
  • 九、集群搭建 —— 多 Master 部署
    • 1、部署Master2组件
    • 2、部署 Nginx 负载均衡
    • 3、部署 KeepAlive

回到顶部https://kubernetes.io/zh/

回到顶部回到顶部回到顶部回到顶部分发自签名-CA-证书

① K8S 证书

如下是 K8S 各个组件需要使用的证书

② 准备 cfssl 工具

我是使用 cfssl 工具来生成证书,首先下载 cfssl 工具。依次执行如下命令:

# curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl
# curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson
# curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo

# chmod +x /usr/local/bin/cfssl*
回到顶部v1.16.2 版本,server 二进制包已经包含了 master、node 上的各个组件,下载 server 二进制包即可。

考虑到网络问题,可以从百度网盘下载已经准备好的二进制包:链接: 下载离线安装包。

将下载好的 kubernetes-v1.16.2-server-linux-amd64.tar.gz 上传到 /usr/local/src下,并解压:

# tar -zxf kubernetes-v1.16.2-server-linux-amd64.tar.gz

先将 master 节点上部署的组件拷贝到 /k8s/kubernetes/bin 目录下:

# cp -p /usr/local/src/kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler} /k8s/kubernetes/bin/

# cp -p /usr/local/src/kubernetes/server/bin/kubectl /usr/local/bin/

② 创建 Node 令牌文件:token.csv

Master apiserver 启用 TLS 认证后,Node节点 kubelet 组件想要加入集群,必须使用CA签发的有效证书才能与apiserver通信,当Node节点很多时,签署证书是一件很繁琐的事情,因此有了 TLS Bootstrap 机制,kubelet 会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。因此先为 apiserver 生成一个令牌文件,令牌之后会在 Node 中用到。

生成 token,一个随机字符串,可使用如下命令生成 token:apiserver 配置的 token 必须与 Node 节点 bootstrap.kubeconfig 配置保持一致。

# head -c 16 /dev/urandom | od -An -t x | tr -d ' '

创建 token.csv,格式:token,用户,UID,用户组

cat > /k8s/kubernetes/cfg/token.csv <<'EOF'
bfa3cb7f6f21f87e5c0e5f25e6cfedad,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF

③ 创建 kube-apiserver 配置文件:kube-apiserver.conf

kube-apiserver 有很多配置项,可以参考官方文档查看每个配置项的用途:kube-apiserver

注意:踩的一个坑,“\” 后面不要有空格,不要有多余的换行,否则启动失败。

cat > /k8s/kubernetes/cfg/kube-apiserver.conf <<'EOF'
KUBE_APISERVER_OPTS="--etcd-servers=https://192.168.31.24:2379,https://192.168.31.35:2379,https://192.168.31.71:2379 \
  --bind-address=192.168.31.24 \
  --secure-port=6443 \
  --advertise-address=192.168.31.24 \
  --allow-privileged=true \
  --service-cluster-ip-range=10.0.0.0/24 \
  --service-node-port-range=30000-32767 \
  --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
  --authorization-mode=RBAC,Node \
  --enable-bootstrap-token-auth=true \
  --token-auth-file=/k8s/kubernetes/cfg/token.csv \
  --kubelet-client-certificate=/k8s/kubernetes/ssl/kubernetes.pem \
  --kubelet-client-key=/k8s/kubernetes/ssl/kubernetes-key.pem \
  --tls-cert-file=/k8s/kubernetes/ssl/kubernetes.pem \
  --tls-private-key-file=/k8s/kubernetes/ssl/kubernetes-key.pem \
  --client-ca-file=/k8s/kubernetes/ssl/ca.pem \
  --service-account-key-file=/k8s/kubernetes/ssl/ca-key.pem \
  --etcd-cafile=/k8s/etcd/ssl/ca.pem \
  --etcd-certfile=/k8s/etcd/ssl/etcd.pem \
  --etcd-keyfile=/k8s/etcd/ssl/etcd-key.pem \
  --v=2 \
  --logtostderr=false \
  --log-dir=/k8s/kubernetes/logs \
  --audit-log-maxage=30 \
  --audit-log-maxbackup=3 \
  --audit-log-maxsize=100 \
  --audit-log-path=/k8s/kubernetes/logs/k8s-audit.log"
EOF

重点配置说明:

  • --etcd-servers:etcd 集群地址
  • --bind-address:apiserver 监听的地址,一般配主机IP
  • --secure-port:监听的端口
  • --advertise-address:集群通告地址,其它Node节点通过这个地址连接 apiserver,不配置则使用 --bind-address
  • --service-cluster-ip-range:Service 的 虚拟IP范围,以CIDR格式标识,该IP范围不能与物理机的真实IP段有重合。
  • --service-node-port-range:Service 可映射的物理机端口范围,默认30000-32767
  • --admission-control:集群的准入控制设置,各控制模块以插件的形式依次生效,启用RBAC授权和节点自管理
  • --authorization-mode:授权模式,包括:AlwaysAllow,AlwaysDeny,ABAC(基于属性的访问控制),Webhook,RBAC(基于角色的访问控制),Node(专门授权由 kubelet 发出的API请求)。(默认值"AlwaysAllow")。
  • --enable-bootstrap-token-auth:启用TLS bootstrap功能
  • --token-auth-file:这个文件将被用于通过令牌认证来保护API服务的安全端口。
  • --v:指定日志级别,0~8,越大日志越详细

④ 创建 apiserver 服务:kube-apiserver.service

cat > /usr/lib/systemd/system/kube-apiserver.service <<'EOF'
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
EnvironmentFile=-/k8s/kubernetes/cfg/kube-apiserver.conf
ExecStart=/k8s/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF

⑤ 启动 kube-apiserver 组件

启动组件

# systemctl daemon-reload
# systemctl start kube-apiserver
# systemctl enable kube-apiserver

检查启动状态

# systemctl status kube-apiserver.service

查看启动日志

# less /k8s/kubernetes/logs/kube-apiserver.INFO

⑥ 将 kubelet-bootstrap 用户绑定到系统集群角色,之后便于 Node 使用token请求证书

kubectl create clusterrolebinding kubelet-bootstrap \
  --clusterrole=system:node-bootstrapper \
  --user=kubelet-bootstrap
kube-controller-manager

cat > /k8s/kubernetes/cfg/kube-controller-manager.conf <<'EOF'
KUBE_CONTROLLER_MANAGER_OPTS="--leader-elect=true \
  --master=127.0.0.1:8080 \
  --address=127.0.0.1 \
  --allocate-node-cidrs=true \
  --cluster-cidr=10.244.0.0/16 \
  --service-cluster-ip-range=10.0.0.0/24 \
  --cluster-signing-cert-file=/k8s/kubernetes/ssl/ca.pem \
  --cluster-signing-key-file=/k8s/kubernetes/ssl/ca-key.pem \
  --root-ca-file=/k8s/kubernetes/ssl/ca.pem \
  --service-account-private-key-file=/k8s/kubernetes/ssl/ca-key.pem \
  --experimental-cluster-signing-duration=87600h0m0s \
  --v=2 \
  --logtostderr=false \
  --log-dir=/k8s/kubernetes/logs"
EOF

重点配置说明:

  • --leader-elect:当该组件启动多个时,自动选举,默认true
  • --master:连接本地apiserver,apiserver 默认会监听本地8080端口
  • --allocate-node-cidrs:是否分配和设置Pod的CDIR
  • --service-cluster-ip-range:Service 集群IP段

② 创建 kube-controller-manager 服务:kube-controller-manager.service

cat > /usr/lib/systemd/system/kube-controller-manager.service <<'EOF'
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
EnvironmentFile=/k8s/kubernetes/cfg/kube-controller-manager.conf
ExecStart=/k8s/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF

③ 启动 kube-controller-manager 组件

启动组件

# systemctl daemon-reload
# systemctl start kube-controller-manager
# systemctl enable kube-controller-manager

检查启动状态

# systemctl status kube-controller-manager.service

查看启动日志

# less /k8s/kubernetes/logs/kube-controller-manager.INFO
回到顶部https://docs.docker.com/install/linux/docker-ce/centos/

① 卸载旧版本

# yum remove docker docker-common docker-selinux

② 安装依赖包

# yum install -y yum-utils device-mapper-persistent-data lvm2

③ 安装 Docker 软件包源

# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

④ 安装 Docker CE

# yum install docker-ce

⑤ 启动 Docker 服务

# systemctl start docker

⑥ 设置开机启动

# systemctl enable docker

⑦ 验证安装是否成功

# docker -v
# docker info

flannel 网络架构

② 创建 CNI 工作目录

通过给 kubelet 传递 --network-plugin=cni 命令行选项来启用 CNI 插件。 kubelet 从 --cni-conf-dir (默认是 /etc/cni/net.d)读取配置文件并使用该文件中的 CNI 配置来设置每个 pod 的网络。CNI 配置文件必须与 CNI 规约匹配,并且配置引用的任何所需的 CNI 插件都必须存在于 --cni-bin-dir(默认是 /opt/cni/bin)指定的目录。

由于前面部署 kubelet 服务时,指定了 --cni-conf-dir=/etc/cni/net.d--cni-bin-dir=/opt/cni/bin,因此首先在node节点上创建这两个目录:

# mkdir -p /opt/cni/bin /etc/cni/net.d

③ 装 CNI 插件

可以从 github 上下载 CNI 插件:下载 CNI 插件 。

解压到 /opt/cni/bin:

# tar zxf cni-plugins-linux-amd64-v0.8.2.tgz -C /opt/cni/bin/

④ 部署 Flannel

可通过此地址下载 flannel 配置文件:下载 kube-flannel.yml

注意如下配置:Network 的地址需与 kube-controller-manager.conf 中的 --cluster-cidr=10.244.0.0/16 保持一致。

在 k8s-master-1 节点上部署 Flannel:

# kubectl apply -f kube-flannel.yml

⑤ 检查部署状态

Flannel 会在 Node 上起一个 Flannel 的 Pod,可以查看 pod 的状态看 flannel 是否启动成功:

# kubectl get pods -n kube-system -o wide

 Flannel 部署成功后,就可以看 Node 是否就绪:

# kubectl get nodes -o wide

在 Node 上查看网络配置,可以看到多了一个 flannel.1 的虚拟网卡,这块网卡用于接收 Pod 的流量并转发出去。

⑥ 测试创建 Pod

例如创建一个 Nginx 服务:

# kubectl create deployment web --image=nginx

查看 Pod 状态:

在对应的节点上可以看到部署的容器:

容器创建成功后,再在 Node 上查看网络配置,又多了一块 cni0 的虚拟网卡,cni0 用于 pod 本地通信使用。

暴露端口并访问 Nginx:

# kubectl expose deployment web --port=80 --type=NodePort

coredns.yaml

注意如下 clusterIP 一定要与 kube-config.yaml 中的 clusterDNS 保持一致

部署 CoreDNS:

$ kubectl apply -f coredns.yaml

② 验证 CoreDNS

创建 busybox 服务:

# cat > busybox.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  dnsPolicy: ClusterFirst
  containers:
  - name: busybox
    image: busybox:1.28.4
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
EOF

# kubectl apply -f busybox.yaml

验证是否安装成功:

回到顶部kubernetes-dashboard.yaml

下载下来之后,需更新如下内容:通过 Node 暴露端口访问 dashboard

部署 dashboard:

# kubectl apply -f kubernetes-dashboard.yaml

查看是否部署成功:

通过 https 访问 dashboard:

回到顶部

九、集群搭建 —— 多 Master 部署

1、部署Master2组件

① 将 k8s-master-1 上相关文件拷贝到 k8s-master-2 上

创建k8s工作目录:

# mkdir -p /k8s/kubernetes
# mkdir -p /k8s/etcd

拷贝 k8s 配置文件、执行文件、证书:

# scp -r /k8s/kubernetes/{cfg,ssl,bin} root@k8s-master-2:/k8s/kubernetes
# cp /k8s/kubernetes/bin/kubectl /usr/local/bin/

拷贝 etcd 证书:

# scp -r /k8s/etcd/ssl root@k8s-master-2:/k8s/etcd

拷贝 k8s 服务的service文件:

# scp /usr/lib/systemd/system/kube-* root@k8s-master-2:/usr/lib/systemd/system

② 修改 k8s-master-2 上的配置文件

修改 kube-apiserver.conf,修改IP为本机IP

③ 启动 k8s-master-2 组件

重新加载配置:

# systemctl daemon-reload

启动 kube-apiserver:

# systemctl start kube-apiserver
# systemctl enable kube-apiserver

启动 kube-controller-manager:

# systemctl start kube-controller-manager
# systemctl enable kube-controller-manager

部署 kube-scheduler:

# systemctl start kube-scheduler
# systemctl enable kube-scheduler

④ 验证

2、部署 Nginx 负载均衡

为了保证 k8s master 的高可用,将使用 k8s-lb-master 和 k8s-lb-backup 这两台机器来部署负载均衡。这里使用 nginx 做负载均衡器,下面分别在 k8s-lb-master 和 k8s-lb-backup 这两台机器上部署 nginx。

① gcc等环境安装,后续有些软件安装需要这些基础环境

# gcc安装:
# yum install gcc-c++
# PCRE pcre-devel 安装:
# yum install -y pcre pcre-devel
# zlib 安装:
# yum install -y zlib zlib-devel
#OpenSSL 安装:
# yum install -y openssl openssl-devel

② 安装nginx

# rpm -ivh https://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.16.1-1.el7.ngx.x86_64.rpm

③ apiserver 负载配置

# vim /etc/nginx/nginx.conf

增加如下配置:

stream {
    log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
    access_log /var/log/nginx/k8s-access.log main;

    upstream k8s-apiserver {
        server 192.168.31.24:6443;
        server 192.168.31.26:6443;
    }

    server {
        listen 6443;
        proxy_pass k8s-apiserver;
    }
}

④ 启动 nginx

# systemctl start nginx
# systemctl enable nginx

3、部署 KeepAlive

为了保证 nginx 的高可用,还需要部署 keepalive,keepalive 主要负责 nginx 的健康检查和故障转移。

① 分别在 k8s-lb-master 和 k8s-lb-backup 这两台机器上安装 keepalive

# yum install keepalived -y

② master 启动 keepalived

修改 k8s-lb-master keepalived 配置文件

cat > /etc/keepalived/keepalived.conf <<'EOF'
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_MASTER
}

vrrp_script check_nginx {
   script "/etc/keepalived/check_nginx.sh" 
}

# vrrp实例
vrrp_instance VI_1 {
    state MASTER 
    interface ens33 
    virtual_router_id 51 
    priority 100
    advert_int 1 
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.31.100/24 
    }
    track_script {
        check_nginx
    }
}
EOF

配置说明:

  • vrrp_script:用于健康检查nginx状态,如果nginx没有正常工作,就会进行故障漂移,使备节点接管VIP,这里通过 shell 脚本来检查nginx状态
  • state:keepalived 角色,主节点为 MASTER,备节点为 BACKUP
  • interface:接口,配置本地网卡名,keepalived 会将虚拟IP绑定到这个网卡上
  • virtual_router_id:#VRRP 路由ID实例,每个实例是唯一的
  • priority:优先级,备服务器设置90
  • advert_int:指定VRRP心跳包通告间隔时间,默认1秒
  • virtual_ipaddress:VIP,要与当前机器在同一网段,keepalived 会在网卡上附加这个IP,之后通过这个IP来访问Nginx,当nginx不可用时,会将此虚拟IP漂移到备节点上。

增加 check_nginx.sh 脚本,通过此脚本判断 nginx 是否正常:

cat > /etc/keepalived/check_nginx.sh <<'EOF'
#!/bin/bash
count=$(ps -ef | grep nginx | egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
    exit 1;
else 
    exit 0;
fi
EOF

增加可执行权限:

# chmod +x /etc/keepalived/check_nginx.sh

启动 keepalived:

# systemctl start keepalived
# systemctl enable keepalived

③ backup 启动 keepalived

修改 k8s-lb-backup keepalived 配置文件

cat > /etc/keepalived/keepalived.conf <<'EOF'
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_BACKUP
}

vrrp_script check_nginx {
   script "/etc/keepalived/check_nginx.sh"
}

# vrrp实例
vrrp_instance VI_1 {
    state BACKUP
    interface eno16777736
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.31.100/24
    }
    track_script {
        check_nginx
    }
}
EOF

增加 check_nginx.sh 脚本:

cat > /etc/keepalived/check_nginx.sh <<'EOF'
#!/bin/bash
count=$(ps -ef | grep nginx | egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
    exit 1;
else 
    exit 0;
fi
EOF

增加可执行权限:

# chmod +x /etc/keepalived/check_nginx.sh

启动 keepalived:

# systemctl start keepalived
# systemctl enable keepalived

④ 验证负载均衡

keepalived 已经将VIP附加到MASTER所在的网卡上

BACKUP节点上并没有

关闭 k8s-lb-master 上的nginx,可看到VIP已经不在了

可以看到已经漂移到备节点上了,如果再重启 MASTER 上的 Ngnix,VIP又会漂移到主节点上。

访问虚拟IP还是可以访问的

4、Node节点连接VIP

① 修改 node 节点的配置文件中连接 k8s-master 的IP为VIP

② 重启 kubelet 和 kube-proxy

# systemctl restart kubelet
# systemctl restart kube-proxy

③ 在 node 节点上访问VIP调用 apiserver 验证

Authorization 的token 是前面生成 token.csv 中的令牌。

至此,通过二进制方式安装 K8S 集群就算完成了!!