实验环境:VMware Fusion 11.0.2
操作系统:CentOS 7.6
主机名 | IP地址 | CPU | 内存 |
---|---|---|---|
k8s2m | 172.16.183.151 | 2核 | 4G |
k8s2n | 172.16.183.161 | 1核 | 1G |
装系统的时候就已经设置为静态IP了,语言为英语,时区是上海。另外因为kubernetes默认不支持swap分区,所以在硬盘分区的时候直接把swap分区拿掉了。这里可以先忽略这些。
如果装系统时分配了 swap 分区,临时关闭 swap 分区可以用: swapoff -a ,永久关闭可以在 /etc/fstab 里面注释掉,这段开始忘了写了,用红色写出来吧。
未声明的话,下列命令在 k8s2m 和 k8s2n 上都能执行。
1、配置 SSH 免密登陆
在本机的hosts 文件中加入如下内容:
代码语言:javascript复制72.16.183.151 k8s2m
172.16.183.161 k8s2n
然后查看本机是否有 id_rsa.pub 文件,如果没有则通过 ssh-keygen 生成
代码语言:javascript复制if [ -f "$HOME/.ssh/id_rsa.pub" ];then echo "File exists"; else ssh-keygen; fi
将本地公钥安装到虚拟机的root账户下
代码语言:javascript复制ssh-copy-id root@k8s2m
ssh-copy-id root@k8s2n
至此免密登陆配置完成。
2、解决 setLocale 问题
接下来开两个终端通过ssh进入系统,在终端得到如下输出:
代码语言:javascript复制-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
在终端直接执行如下命令,然后退出ssh,再次进入,或者直接重启虚拟机
代码语言:javascript复制cat <<EOF > /etc/environment
LANG=en_US.UTF-8
LC_ALL=C
EOF
3、设置 SELinux 为 permissive 模式
代码语言:javascript复制setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
4、停止并且禁用动态防火墙
代码语言:javascript复制systemctl disable firewalld && systemctl stop firewalld
5、添加 kubernetes.repo 和 docker-ce.repo
原本是都用 cat EOF 方式来做的,结果发现在我MAC上SSH连接进去执行后文件内容一致,但即便 yum clean all 后仍然无法生效,这里还是使用 vi,vim等编辑器往里面粘贴算了。
vi /etc/yum.repos.d/kubernetes.repo
代码语言:javascript复制[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
vi /etc/yum.repos.d/docker-ce.repo
代码语言:javascript复制[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-stable-debuginfo]
name=Docker CE Stable - Debuginfo $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/debug-$basearch/stable
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-stable-source]
name=Docker CE Stable - Sources
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/source/stable
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-edge]
name=Docker CE Edge - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/edge
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-edge-debuginfo]
name=Docker CE Edge - Debuginfo $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/debug-$basearch/edge
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-edge-source]
name=Docker CE Edge - Sources
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/source/edge
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-test]
name=Docker CE Test - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/test
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-test-debuginfo]
name=Docker CE Test - Debuginfo $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/debug-$basearch/test
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-test-source]
name=Docker CE Test - Sources
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/source/test
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-nightly]
name=Docker CE Nightly - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/nightly
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-nightly-debuginfo]
name=Docker CE Nightly - Debuginfo $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/debug-$basearch/nightly
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-nightly-source]
name=Docker CE Nightly - Sources
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/source/nightly
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
6、安装 docker-ce
这里kubeadm的版本是1.13.1,支持的 docker 版本最高应该是 18.06.x,通过执行 yum list docker-ce --showduplicates | sort -r 得到 docker 各版本的列表:
这里选 18.06.1.ce-3.el7
代码语言:javascript复制docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 18.03.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.12.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.12.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.09.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.09.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.3.ce-1.el7 docker-ce-stable
docker-ce.x86_64 17.03.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable
安装 docker-ce:
代码语言:javascript复制yum install -y docker-ce-18.06.1.ce-3.el7
启动 docker 服务,并将 docker 服务设置为开机启动
代码语言:javascript复制systemctl enable docker && systemctl start docker
7、安装 kubelet、kubeadm 和 kubectl
以下是安装 kubernetes 所需的工具
代码语言:javascript复制yum install -y kubelet kubeadm kubectl
启动 docker、kubelet 服务,并将 docker、kubelet 服务设置为开机启动
代码语言:javascript复制systemctl enable kubelet && systemctl start kubelet
8、安装镜像
列出 kubeadm 需要安装的镜像列表,然后使用 sed 修改后执行:
代码语言:javascript复制kubeadm config images list |sed -e 's#k8s.gcr.io/coredns#coredns/coredns#g'|sed -e 's/^/docker pull /g' -e 's#k8s.gcr.io#mirrorgooglecontainers#g'|sh -x
装好的镜像 tag 跟 kubeadm 直接装的是不一样的,这里给予修正:
代码语言:javascript复制docker images |grep -E 'mirrorgooglecontainers|coredns/coredns'|awk '{print "docker tag ",$1":"$2,$1":"$2}'|sed -e 's#mirrorgooglecontainers#k8s.gcr.io#2'|sed -e 's#coredns#k8s.gcr.io#3'|sh -x
最后移除掉多余的 tag
代码语言:javascript复制docker images |grep -E 'mirrorgooglecontainers|coredns/coredns'|awk '{print "docker rmi ",$1":"$2}'|sh -x
9、配置 net.bridge.bridge-nf-call-iptables
代码语言:javascript复制cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
然后重启 kubelet
代码语言:javascript复制systemctl daemon-reload
systemctl restart kubelet
10、创建kubernetes master,只需要在 master 节点(k8s2m)上执行
在 master 上执行下面命令创建 kubernetes master,为何加 --pod-network-cidr=10.244.0.0/16 看这里
代码语言:javascript复制kubeadm init --pod-network-cidr=10.244.0.0/16
命令执行结束后,根据提示执行如下操作,如果本身是 root 用户,第三条其实不用执行的:
代码语言:javascript复制mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
下面还有一条如下形式的提示,拷贝出来,在 worker 节点(k8s2n)上需要执行
代码语言:javascript复制kubeadm join 172.16.183.151:6443 --token ############## --discovery-token-ca-cert-hash #############################
最后安装 pod network add-on,这里装 flannel,在安装之前这里有如下说明,也是为何
代码语言:javascript复制链接地址: https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#tabs-pod-install-4
For flannel to work correctly, you must pass --pod-network-cidr=10.244.0.0/16 to kubeadm init.
安装flannel
代码语言:javascript复制kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
如果想要查看 pods 或 nodes,分别执行如下命令(另外 pods 就是跑在 docker 上的,也可以通过 docker ps 来查看):
代码语言:javascript复制 kubectl get pods --all-namespaces
kubectl get nodes --all-namespaces
想要查看实时状态还可以执行如下命令,-n2也就是2秒刷新一次结果:
代码语言:javascript复制watch -n2 kubectl get pods --all-namespaces
watch -n2 kubectl get nodes --all-namespaces
11、将 worker 节点(k8s2n) 加入 master 节点(k8s2m)
最后只需要在 worker 节点(k8s2n)上执行如下命令(在 master 节点 init 结束让存下的命令):
代码语言:javascript复制kubeadm join 172.16.183.151:6443 --token ############## --discovery-token-ca-cert-hash #############################
当在master 节点 (k8s2m) 执行 kubectl get nodes ,能看到两个节点,并且状态都是 Ready 的时候,这里的任务也就暂时完成了。