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-bootstrapkube-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 -vflannel 网络架构
# docker info
② 创建 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=NodePortcoredns.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 集群就算完成了!!