0、k8s的安装以及基础pod方式搭建
0、准备的主机
Kubernetes技术已经成为了原生云技术的事实标准,它是目前基础软件领域最为热门的分布式调度和管理平台。于是,Kubernetes也几乎成了时下开发工程师和运维工程师必备的技能之一。
Master01 | 192.168.1.20 |
---|---|
Node01 | 192.168.1.21 |
Node02 | 192.168.1.22 |
Node03 | 192.168.1.23 |
ssh-keygen两两交换
1、主机名
$ vim /etc/hosts
192.168.1.20 master01 master01.wuyanzu.com
192.168.1.21 node01 node01.wuyanzu.com
192.168.1.22 node02 node02.wuyanzu.com
192.168.1.23 node03 node03.wuyanzu.com
节点的 hostname 必须使用标准的 DNS 命名,另外千万不用什么默认的
localhost
的 hostname,会导致各种错误出现的。在 Kubernetes 项目里,机器的名字以及一切存储在 Etcd 中的 API 对象,都必须使用标准的 DNS 命名(RFC 1123)。
$ scp /etc/hosts 192.168.1.21:/etc/
$ scp /etc/hosts 192.168.1.22:/etc/
$ scp /etc/hosts 192.168.1.23:/etc/
2、禁用防火墙与SELINUX
$ systemctl stop firewalld.service
$ systemctl stop iptables.service
$ systemctl disable firewalld.service
$ systemctl disable iptables.service
$ setenforce 0
$ cat /etc/selinux/config
SELINUX=disabled
# 使用sed
$ sed -i 's@^\(SELINUX=\).*@\1disabled@' /etc/sysconfig/selinux
3、同步服务器时间
$ yum install chrony -y && systemctl enable chronyd &&systemctl start chronyd
# 同步时间
$ chronyc sources
$ date
不过,建议用户配置使用本地的的时间服务器,在节点数量众多时尤其如此。存在可用的本地时间服务器时,修改节点的/etc/crhony.conf配置文件,并将时间服务器指向相应的主机即可,配置格式如下:
server CHRONY-SERVER-NAME-OR-IP iburst
4、禁用Swap设备
部署集群时,kubeadm默认会预先检查当前主机是否禁用了Swap设备,并在未禁用时强制终止部署过程。因此,在主机内存资源充裕的条件下,需要禁用所有的Swap设备,否则,就需要在后文的kubeadm init及kubeadm join命令执行时额外使用相关的选项忽略检查错误。
$ free -m
total used free shared buff/cache available
Mem: 954 147 440 9 366 653
Swap: 2047 9 2038
#临时
$ swapoff -a
$ free -m
total used free shared buff/cache available
Mem: 954 150 433 12 370 646
Swap: 0 0 0
关闭Swap设备,需要分两步完成。首先是关闭当前已启用的所有Swap设备:
$ swapoff -a
修改/etc/fstab
文件,注释掉 SWAP 的自动挂载。swappiness 参数调整,修改/etc/sysctl.d/k8s.conf
添加下面一行:
$ vim /etc/sysctl.d/k8s.conf
vm.swappiness=0
$ sysctl -p /etc/sysctl.d/k8s.conf
5、启用ipvs内核模块
由于开启内核 ipv4 转发需要加载 br_netfilter 模块,所以加载下该模块:
$ modprobe br_netfilter
$ vim /etc/sysctl.d/k8s.conf
vm.swappiness=0
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
$ sysctl -p /etc/sysctl.d/k8s.conf
$ scp /etc/sysctl.d/k8s.conf node01:/etc/sysctl.d/
$ scp /etc/sysctl.d/k8s.conf node02:/etc/sysctl.d/
$ scp /etc/sysctl.d/k8s.conf node03:/etc/sysctl.d/
bridge-nf
bridge-nf 使得 netfilter 可以对 Linux 网桥上的 IPv4/ARP/IPv6 包过滤。
比如,设置net.bridge.bridge-nf-call-iptables=1后,二层的网桥在转发包时也会被 iptables的 FORWARD 规则所过滤。常用的选项包括:
net.bridge.bridge-nf-call-arptables:是否在 arptables 的 FORWARD 中过滤网桥的 ARP 包
net.bridge.bridge-nf-call-ip6tables:是否在 ip6tables 链中过滤 IPv6 包
net.bridge.bridge-nf-call-iptables:是否在 iptables 链中过滤 IPv4 包
net.bridge.bridge-nf-filter-vlan-tagged:是否在 iptables/arptables 中过滤打了 vlan 标签的包。
安装 ipvs
$ cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
$ chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
上面脚本创建了的/etc/sysconfig/modules/ipvs.modules
文件,保证在节点重启后能自动加载所需模块。使用lsmod | grep -e ip_vs -e nf_conntrack_ipv4
命令查看是否已经正确加载所需的内核模块。
接下来还需要确保各个节点上已经安装了 ipset 软件包:
$ yum install ipset -y
为了便于查看 ipvs 的代理规则,最好安装一下管理工具 ipvsadm:
$ yum install ipvsadm -y
6、安装docker
[docker-ce]
name=docker
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/
$ yum install docker-ce -y --nogpgcheck
$ systemctl start docker
$ systemctl enable docker.service
配置镜像加速器
$ mkdir -p /etc/docker
$ vim /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"registry-mirrors" : [
"https://sw9esv3f.mirror.aliyuncs.com"
]
}
sudo systemctl daemon-reload
sudo systemctl restart docker
$ scp /etc/docker/daemon.json node01:/etc/docker/
$ scp /etc/docker/daemon.json node02:/etc/docker/
$ scp /etc/docker/daemon.json node03:/etc/docker/
cgroup 驱动
由于默认情况下 kubelet 使用的 cgroupdriver 是 systemd,所以需要保持 docker 和kubelet 的 cgroupdriver 一致,我们这里修改 docker 的 cgroupdriver=systemd。如果不修改 docker 则需要修改 kubelet 的启动配置,需要保证两者一致。
docker命令补全
sudo yum install -y bash-completion
#登出一下再进来即可
7、安装k8s
1-7是所有主机都要执行的
[kubernetes]
name=kubernetes
baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/yum/repos/kubernetes-el7-x86_64/
--disableexcludes 禁掉除了kubernetes之外的别的仓库
$ yum install kubelet kubeadm kubectl -y --nogpgcheck --disableexcludes=kubernetes
# 查看版本
$ kubeadm version
#设置为开机启动
$ systemctl enable --now kubelet
8、初始化集群
master 节点配置 kubeadm 初始化文件,可以通过如下命令导出默认的初始化配置:
8.1、通过配置文件加载配置
$ kubeadm config print init-defaults > kubeadm.yaml
然后根据我们自己的需求修改配置,比如修改 imageRepository 的值,kube-proxy 的模式为 ipvs,另外需要注意的是我们这里是准备安装 flannel 网络插件的,需要将 networking.podSubnet 设置为10.244.0.0/16
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.1.20 # apiserver 节点内网IP
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: master1
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
# registry.aliyuncs.com/k8sxio # 修改成阿里云镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.21.1
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16 # Pod 网段,flannel插件需要使用这个网段
serviceSubnet: 10.96.0.0/12
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs # kube-proxy 模式
godoc 文档:完整的资源对象对应的属性
https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2。
$ kubeadm init --config kubeadm.yaml
kubectl是kube-apiserver的命令行客户端程序,实现了除系统部署之外的几乎全部的管理操作,是kubernetes管理员使用最多的命令之一。kubectl需经由API server认证及授权后方能执行相应的管理操作,kubeadm部署的集群为其生成了一个具有管理员权限的认证配置文件/etc/kubernetes/admin.conf,它可由kubectl通过默认的“$HOME/.kube/config”的路径进行加载。当然,用户也可在kubectl命令上使用--kubeconfig选项指定一个别的位置。
下面复制认证为Kubernetes系统管理员的配置文件至目标用户(例如当前用户root)的家目录下:
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
8.2、命令行初始化方式
$ kubeadm init --kubernetes-version=v1.21.1 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --image-repository registry.aliyuncs.com/google_containers --ignore-preflight-errors=Swap
命令中的各选项简单说明如下:
- --kubernetes-version选项的版本号用于指定要部署的Kubenretes程序版本,它需要与当前的kubeadm支持的版本保持一致;
- --pod-network-cidr选项用于指定分Pod分配使用的网络地址,它通常应该与要部署使用的网络插件(例如flannel、calico等)的默认设定保持一致,10.244.0.0/16是flannel默认使用的网络;
- --service-cidr用于指定为Service分配使用的网络地址,它由kubernetes管理,默认即为10.96.0.0/12;
- 最后一个选项“--ignore-preflight-errors=Swap”仅应该在未禁用Swap设备的状态下使用。
注意初始化的时候coredns在阿里云的有点不一致,所以需要手动去拉一下,然后去打下标签在初始化
$ docker pull registry.aliyuncs.com/google_containers/coredns:1.8.0
$ docker tag registry.aliyuncs.com/google_containers/coredns:1.8.0 registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0
$ docker rmi registry.aliyuncs.com/google_containers/coredns:1.8.0
在各个node节点中也是需要手动拉改的
如果没有得到全是OK的结果
# 是/etc/kubernetes/manifests下的kube-controller-manager.yaml和kube-scheduler.yaml设置的默认端口是0导致
$ kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Unhealthy Get http://127.0.0.1:10251/healthz: dial tcp 127.0.0.1:10251: connect: connection refused
controller-manager Unhealthy Get http://127.0.0.1:10252/healthz: dial tcp 127.0.0.1:10252: connect: connection refused
etcd-0 Healthy {"health":"true"}
# kube-scheduler.yaml配置修改:注释掉19行
$ vim /etc/kubernetes/manifests/kube-scheduler.yaml
...
16 - --bind-address=127.0.0.1
17 - --kubeconfig=/etc/kubernetes/scheduler.conf
18 - --leader-elect=true
19 # - --port=0
...
# kube-controller-manager.yaml文件修改:注释掉27行
$ vim /etc/kubernetes/manifests/kube-controller-manager.yaml
...
22 - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
23 - --controllers=*,bootstrapsigner,tokencleaner
24 - --kubeconfig=/etc/kubernetes/controller-manager.conf
25 - --leader-elect=true
26 - --node-cidr-mask-size=24
27 # - --port=0
...
$ kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
kubeadm init
命令执行流程图
9、添加节点
安装 kubeadm、kubelet、kubectl(可选)
# 将 master 节点上面的 ~/.kube/config 文件拷贝到 node 节点对应的文件中,这样每个node也可以查看面板
$ scp ~/.kube/config node01:~/.kube/
$ scp ~/.kube/config node02:~/.kube/
$ scp ~/.kube/config node03:~/.kube/
# 查看token
$ kubeadm token list
# 查看--discovery-token-ca-cert-hash
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
# 或者2者
$ kubeadm token create --print-join-command
kubeadm join 192.168.1.20:6443 --token bhq4ro.jieonxs43q0iimal --discovery-token-ca-cert-hash sha256:37ea892c7874b116e24b63ab1403dbe9573e9414beb2d07e2547cad6000fa6f3
join执行流程图
10、网络插件
Kubernetes系统上Pod网络的实现依赖于第三方插件进行,这类插件有近数十种之多,较为著名的有flannel、calico、canal和kube-router等,简单易用的实现是为CoreOS提供的flannel项目。下面的命令用于在线部署flannel至Kubernetes系统之上:
$ wget -e "https_proxy=http://192.168.1.6:7890" https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 因为有节点是多网卡,所以需要在资源清单文件中指定内网网卡
# 搜索到名为 kube-flannel-ds 的 DaemonSet,在kube-flannel容器下面
$ vim kube-flannel.yml
......
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.13.0
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=eth0 # 如果是多网卡的话,指定内网网卡的名称
......
# 安装 flannel 网络插件
$ kubectl apply -f kube-flannel.yml
# 全部显示ready表示成功建立flannel隧道
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
node Ready control-plane,master 30m v1.21.1
node01 Ready <none> 26m v1.21.1
node02 Ready <none> 19m v1.21.1
node03 Ready <none> 19m v1.21.1
# 查看主节点的配置信息
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.1.20:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
11、Dashboard(简单使用)
$ wget -e "https_proxy=http://192.168.1.6:7890" https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml
$ vim recommended.yaml
# 修改Service为NodePort类型
......
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
type: NodePort # 加上type=NodePort变成NodePort类型的服务,向外暴露端口
......
$ kubectl apply -f recommended.yaml
$ kubectl get pods -n kubernetes-dashboard
NAME READY STATUS RESTARTS AGE
dashboard-metrics-scraper-856586f554-sjcrw 1/1 Running 0 82s
kubernetes-dashboard-78c79f97b4-j6sd6 1/1 Running 0 82s
$ kubectl get svc -n kubernetes-dashboard
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.97.149.154 <none> 8000/TCP 102s
kubernetes-dashboard NodePort 10.99.166.71 <none> 443:32660/TCP 102s
在 YAML 文件中可以看到新版本 Dashboard 集成了一个 metrics-scraper 的组件,可以通过 Kubernetes 的 Metrics API 收集一些基础资源的监控信息,并在 web 页面上展示,所以要想在页面上展示监控信息就需要提供 Metrics API,比如安装 Metrics Server。
使用火狐测试192.168.1.20:32660(任何一个节点IP)
然后创建一个具有全局所有权限的用户来登录Dashboard:(admin.yaml)
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kubernetes-dashboard
$ kubectl apply -f admin.yaml
$ kubectl get secret -n kubernetes-dashboard
NAME TYPE DATA AGE
admin-token-tm8hk kubernetes.io/service-account-token 3 32s
default-token-5zq2k kubernetes.io/service-account-token 3 8m15s
kubernetes-dashboard-certs Opaque 0 8m15s
kubernetes-dashboard-csrf Opaque 1 8m15s
kubernetes-dashboard-key-holder Opaque 2 8m15s
kubernetes-dashboard-token-qq9zn kubernetes.io/service-account-token 3 8m15s
$ kubectl describe secret admin-token-wj5hg -n kubernetes-dashboard
...
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IklsTGNCZ1oxREpHLUZ2M0xTMHg4UFo5Ym14QUdrZkd2S2VwcHNrM1FPc00ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi10b2tlbi13ajVoZyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImZkNWVkNTY4LTAwMzctNDJiMy1iMDQ3LTU3NDhmZTM4M2NjNSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDphZG1pbiJ9.Lks1svXuk1xwD7xosvgwuApft3zjTUapG6rPacbIrSNkHRL2BfWw6r79-0XtfCCBrTcsggBICJ4gDwBhrh6Iz5veKF2l4dKQcNLODttjm6Bt-1gJlmYxx-9mrige4tpXEjm7YAeXE8cqnDM_wG9Zrar2JRm3S-FvQAI9jf79q_4H-WuMvCQ0iuQJ80yk2Y-Y6dsTO8E39LujJ6XSiBdEID9vmcNzMBwl3hiJ_StSdqSeYvph-x9F2DDxYsOM9p6OF6wfq87u_wBzqZGH6RzernahXqC9Ror_iUO77_RH-rCApU-RJbPHF94oT_F0EPckCJDi6N9pHLNqpQFxYxU_EQ
...
# 直接一条命令取出来,base64解码后的值
$ kubectl get secrets admin-token-tm8hk -o jsonpath={.data.token} -n kubernetes-dashboard
12、清理
如果你的集群安装过程中遇到了其他问题,我们可以使用下面的命令来进行重置:
$ kubeadm reset
$ ifconfig cni0 down && ip link delete cni0
$ ifconfig flannel.1 down && ip link delete flannel.1
$ rm -rf /var/lib/cni/
13、k8s 命令自动补全
yum install -y bash-completion &&\
source /usr/share/bash-completion/bash_completion &&\
source <(kubectl completion bash) &&\
echo "source <(kubectl completion bash)" >> ~/.bashrc
14、IDE与服务器交互的2种方式
1、sftp连接
见pycharm
2、Bash on MacOS
在 Mac 下面,就稍微复杂一点点了,因为 Mac 上的 Bash 默认版本是3.2,已经过时了,kubectl 的自动补全脚本至少需要 Bash 4.1 版本。
所以要在 Mac 上使用 kubectl 自动补全功能,你就需要安装新版本的 Bash,更新 Bash 是很容易的,可以查看这篇文章:Upgrading Bash on macOS,这里我们就不详细说明了。
在继续向下之前,请确保你的 Bash 版本在 4.1 以上。和 Linux 中一样,Bash 的补全脚本依赖 bash-completion 项目,所以我们也必须要安装它。
我们可以使用 Homebrew 工具来安装:
$ brew install bash-completion@2
@2
代表 bash-completion v2 版本,kubectl 命令补全脚本需要 v2 版本,而 v2 版本至少需要 Bash 4.1 版本,所以这就是不能在低于4.1的 Bash 下面使用 kubectl 的补全脚本的原因。
brew 安装命令完成会输出一段提示信息,其中包含将下面内容添加到~/.bash_profile
文件中的说明:
export BASH_COMPLETION_COMPAT_DIR=/usr/local/etc/bash_completion.d
[[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh"
这样就完成了 bash-completion 的安装,但是建议将上面这一行信息添加到~/.bashrc
当中,这样可以在子 shell 中也可以使用 bash-completion。
重新加载 shell 后,可以使用以下命令测试是否正确安装了 bash-completion:
$ type _init_completion
如果输出一个 shell 函数,证明安装成功了。然后就需要进行一些配置来让我们在所有的 shell 会话中都可以获取 kubectl 补全脚本。
一种方法是将下面的内容添加到~/.bashrc
文件中:
source <(kubectl completion bash)
另外一种方法是添加 kubectl 补全脚本到/usr/local/etc/bash_completion.d
目录下面:
$ kubectl completion bash >/usr/local/etc/bash_completion.d/kubectl
使用 Homebrew 安装 bash-completion 时上面的方法才会生效。
如果你还是使用 Homebrew 安装的 kubectl 的话,上面的步骤都可以省略,因为补全脚本已经被自动放置到/usr/local/etc/bash_completion.d
目录中去了,这种情况,kubectl 命令补全应该在安装完 bash-completion 后就可以正常使用了。
最后,重新加载 shell 后,kubectl 自动提示应该就可以正常工作了。