使用kubeadm方式安装K8S
kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,伴随Kubernetes每个版本的发布都会同步更新,kubeadm会对集群配置方面的一些实践做调整,通过实验kubeadm可以学习到Kubernetes官方在集群配置上一些新的最佳实践。
这个工具能通过两条指令完成一个kubernetes集群的部署:
# 创建一个 Master 节点
kubeadm init
# 将一个 Node 节点加入到当前集群中
kubeadm join <Master节点的IP和端口 >
1. 安装要求
在开始之前,部署Kubernetes集群机器需要满足以下几个条件:
- 一台或多台机器,操作系统 CentOS7.x-86_x64
- 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
- 集群中所有机器之间网络互通
- 可以访问外网,需要拉取镜像
- 禁止swap分区
2. 学习目标
- 在所有节点上安装Docker和kubeadm
- 部署Kubernetes Master
- 部署容器网络插件
- 部署 Kubernetes Node,将节点加入Kubernetes集群中
- 部署Dashboard Web页面,可视化查看Kubernetes资源
3. 准备环境
角色 | IP |
k8s-master | 192.168.150.51 |
k8s-node1 | 192.168.150.55 |
k8s-node2 | 192.168.150.56 |
关闭防火墙:
systemctl stop firewalld
systemctl disable firewalld
关闭selinux:
sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久
setenforce 0 # 临时
关闭swap:
swapoff -a # 临时
vim /etc/fstab # 永久 最后一行#
设置主机名:
hostnamectl set-hostname <hostname>
在master添加hosts:
cat >> /etc/hosts << EOF
192.168.150.51 k8s-master
192.168.150.52 k8s-master2
192.168.150.55 k8s-node1
192.168.150.56 k8s-node2
EOF
将桥接的IPv4流量传递到iptables的链:
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system # 生效
时间同步:
yum install ntpdate -y
ntpdate time.windows.com
4. 所有节点安装Docker/kubeadm/kubelet
Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。
4.1 安装Docker
#安装必要依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
#添加aliyun docker-ce yum源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#重建yum缓存
yum makecache fast
#查看可用docker版本
yum list docker-ce.x86_64 --showduplicates | sort -r
#安装指定版本docker
yum install -y docker-ce-19.03.12-3.el7
#yum install -y docker-ce
systemctl enable docker && systemctl start docker
docker -v
#docker load -i rancher.tar
4.2配置docker
下面为最终文件内容
# cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://e7m5fxhx.mirror.aliyuncs.com",
"https://hub-mirror.c.163.com/",
"https://reg-mirror.qiniu.com"]
}
EOF
mkdir /etc/docker
#修改cgroup驱动为systemd[k8s官方推荐]、限制容器日志量、修改存储类型,最后的docker家目录可修改
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"registry-mirrors": ["https://e7m5fxhx.mirror.aliyuncs.com"],
"data-root": "/data/docker"
}
EOF
#添加开机自启,立即启动
systemctl enable --now docker
验证docker是否正常
#查看docker信息,判断是否与配置一致
docker info
#hello-docker测试
docker run --rm hello-world
#删除测试image
docker rmi hello-world
4.3 配置K8S阿里云yum源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
#重建yum缓存,输入y添加证书认证
yum makecache fast
4.4 安装kubeadm,kubelet和kubectl
各节点均需安装kubeadm、kubelet,kubectl仅kube-master节点需安装(作为worker节点,kubectl无法使用,可以不装)#yum install -y --nogpgcheck kubelet kubeadm kubectl
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
yum install -y kubelet kubeadm --disableexcludes=kubernetes
#开启kubelet,并设置为开机启动
systemctl enable --now kubelet
systemctl enable kubelet && systemctl start kubelet
配置自动补全命令
#安装bash自动补全插件
yum install bash-completion -y
#设置kubectl与kubeadm命令补全,下次login生效
kubectl completion bash >/etc/bash_completion.d/kubectl
kubeadm completion bash > /etc/bash_completion.d/kubeadm
#4.5调整启动方式
kubelet的启动环境变量要与docker的cgroup-driver驱动一样
docker info | grep -i cgroup
Cgroup Driver: cgroupfs --> 运行命令显示
docker的cgroup-driver是cgroupfs,而k8s默认是systemd
修改docker的cgroup-driver
vim /etc/docker/daemon.json
加入内容 : { "exec-opts": ["native.cgroupdriver=systemd"] }
最终文件内容
{
"registry-mirrors": [
"https://e7m5fxhx.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com",
"https://reg-mirror.qiniu.com"
],
"exec-opts": ["native.cgroupdriver=systemd"]
}
重启Docker
systemctl status docker
systemctl restart docker
启动kubelet服务
systemctl enable kubelet.service
systemctl start kubelet.service
5. 部署Kubernetes Master
在192.168.150.51(k8s-master)执行。
kubeadm init \
--apiserver-advertise-address=192.168.150.51 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.19.3 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
--token-ttl 0
–kubernetes-version : 指定版本号 kubectl version查看
–apiserver-advertise-address : 指定主机地址
–image-repository:指定下载镜像服务器为阿里云或者是其他国内镜像仓库地址。
–pod-network-cidr:定义POD的网段为: 10.244.0.0/16,
初始化成功后会返回如下信息
#这个返回信息三条命令是配置kubectl工具的命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
# 这个返回信息是配置Node节点的命令
kubeadm join 192.168.150.51:6443 --token xdl1l6.t9tkhmotr63g63x1 \
--discovery-token-ca-cert-hash sha256:0216be6d3e896f533343a8178a5552cab7b47ca8f52acd30e127cd3888366d6c
配置kubectl工具:运行初始化成功后返回的三条命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
$ kubectl get nodes #查看所有kubelet节点
6. 安装Pod网络插件(CNI)
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
确保能够访问到quay.io这个registery。
如果Pod镜像下载失败,可以改成这个镜像地址:lizhenliang/flannel:v0.11.0-amd64
7. 加入Kubernetes Node
在192.168.150.55/56(Node)执行。
向集群添加新节点,执行在kubeadm init输出的kubeadm join命令:
kubeadm join 192.168.150.51:6443 --token xdl1l6.t9tkhmotr63g63x1 \
--discovery-token-ca-cert-hash sha256:0216be6d3e896f533343a8178a5552cab7b47ca8f52acd30e127cd3888366d6c
8. 测试kubernetes集群
在Kubernetes集群中创建一个pod,验证是否正常运行:
kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/nginx-6799fc88d8-6qdxf 1/1 Running 0 4m53s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 58m
service/nginx NodePort 10.102.217.13 <none> 80:32750/TCP 106s
访问地址:http://192.168.150.51:32750
Kuboard,是一款免费的 Kubernetes 图形化管理工具,Kuboard 力图帮助用户快速在 Kubernetes 上落地微服务。
9.安装Kuboard
Kuboard,是一款免费的 Kubernetes 图形化管理工具,Kuboard 力图帮助用户快速在 Kubernetes 上落地微服务。如果您参考 https://kuboard.cn 网站上提供的 Kubernetes 安装文档,可在 master 节点上执行以下命令。
kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml
kubectl apply -f https://addons.kuboard.cn/metrics-server/0.3.7/metrics-server.yaml
查看 Kuboard 运行状态:
kubectl get pods -l k8s.kuboard.cn/name=kuboard -n kube-system
输出结果如下所示:确保kuboard 处于 Running 状态
NAME READY STATUS RESTARTS AGE
kuboard-756d46c4d4-qh6cm 1/1 Running 0 45s
获取Token
您可以获得管理员用户、只读用户的Token。
Kuboard 有计划开发权限设置的功能,在这之前,如果您需要更细粒度的权限控制,请参考 RBAC Example
管理员用户
此Token拥有 ClusterAdmin 的权限,可以执行所有操作
执行命令
# 如果您参考 www.kuboard.cn 提供的文档安装 Kuberenetes,可在第一个 Master 节点上执行此命令
echo $(kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-user | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d)
输出
取输出信息中 token 字段
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxToken
访问Kuboard
您可以通过NodePort、port-forward 两种方式当中的任意一种访问 Kuboard
通过NodePort访问
Kuboard Service 使用了 NodePort 的方式暴露服务,NodePort 为 32567;您可以按如下方式访问 Kuboard。
http://任意一个Worker节点的IP地址:32567/
输入前一步骤中获得的 token,可进入 Kuboard 集群概览页
通过port-forward访问
在您的客户端电脑中执行如下命令
kubectl port-forward service/kuboard 8080:80 -n kube-system
在浏览器打开链接 (请使用 kubectl 所在机器的IP地址)
http://localhost:8080
输入前一步骤中获得的 token,可进入 Kubernetes 集群概览
TIP:需要您先完成 从客户端电脑远程管理 Kubernetes 的配置
10. 部署 Dashboard
Releases · kubernetes/dashboard · GitHub
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml
查看dashboard运行状态,以deployment方式部署,运行2个pod及2个service:
kubectl -n kubernetes-dashboard get pods
NAME READY STATUS RESTARTS AGE
dashboard-metrics-scraper-7b59f7d4df-dppvl 1/1 Running 0 4m41s
kubernetes-dashboard-74d688b6bc-vfmgk 1/1 Running 0 4m41s
kubectl -n kubernetes-dashboard get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.97.175.133 <none> 8000/TCP 4m44s
kubernetes-dashboard ClusterIP 10.108.225.65 <none> 443/TCP 4m45s
访问dashboard
这里作为演示,使用nodeport方式将dashboard服务暴露在集群外,指定使用30443端口,可自定义:
kubectl patch svc kubernetes-dashboard -n kubernetes-dashboard \
-p '{"spec":{"type":"NodePort","ports":[{"port":443,"targetPort":8443,"nodePort":30443}]}}'
查看暴露的service,已修改为nodeport类型:
kubectl -n kubernetes-dashboard get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.97.175.133 <none> 8000/TCP 6m15s
kubernetes-dashboard NodePort 10.108.225.65 <none> 443:30443/TCP 6m16s
或者下载yaml文件手动修改service部分
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:
more recommended.yaml
...
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30443
selector:
k8s-app: kubernetes-dashboard
---
...
更新配置 kubectl apply -f recommended.yaml
访问地址:http://NodeIP:30443
Dashboard 支持 Kubeconfig 和 Token 两种认证方式,我们这里选择Token认证方式登录。
创建dashboard-adminuser.yaml:
cat > dashboard-adminuser.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOF
创建登录用户
kubectl apply -f dashboard-adminuser.yaml
说明:上面创建了一个叫admin-user的服务账号,并放在kubernetes-dashboard 命名空间下,并将cluster-admin角色绑定到admin-user账户,这样admin-user账户就有了管理员的权限。默认情况下,kubeadm创建集群时已经创建了cluster-admin角色,我们直接绑定即可。
查看admin-user账户的token
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
把获取到的Token复制到登录界面的Token输入框中,成功登陆dashboard:
创建service account并绑定默认cluster-admin管理员集群角色:
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
使用输出的token登录Dashboard。
kubectl get pods --all-namespaces
如果有问题,重新配置Master
kubeadm reset
实战:部署 nginx Deployment
kubectl
创建 YAML 文件
创建文件 nginx-deployment.yaml,内容如下:
apiVersion: apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
kind: Deployment #该配置的类型,我们使用的是 Deployment
metadata: #译名为元数据,即 Deployment 的一些基本属性和信息
name: nginx-deployment #Deployment 的名称
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
app: nginx #为该Deployment设置key为app,value为nginx的标签
spec: #这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用
replicas: 1 #使用该Deployment创建一个应用程序实例
selector: #标签选择器,与上面的标签共同作用,目前不需要理解
matchLabels: #选择包含标签app:nginx的资源
app: nginx
template: #这是选择或创建的Pod的模板
metadata: #Pod的元数据
labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app: nginx
spec: #期望Pod实现的功能(即在pod中部署)
containers: #生成container,与docker中的container是同一种
- name: nginx #container的名称
image: nginx:1.7.9 #使用镜像nginx:1.7.9创建container,该container默认80端口可访问
应用 YAML 文件
kubectl apply -f nginx-deployment.yaml
查看部署结果
# 查看 Deployment
kubectl get deployments
# 查看 Pod
kubectl get pods
可分别查看到一个名为 nginx-deployment 的 Deployment 和一个名为 nginx-deployment-xxxxxxx 的 Pod
~~任务二达成,至此你已经成功在k8s上部署了一个实例的nginx应用程序,
使用 Kuboard
打开 Kuboard 集群概览界面
点击 default 名称空间
点击 创建工作负载
并填写表单如下:
字段名 | 填写内容 | 备注 |
服务类型 | Deployment | |
服务分层 | 展现层 | Kuboard使用这个字段确定将部署显示在微服务架构的哪个分层 |
服务名称 | nginx | 服务分层的前缀 + 服务名 组成最终的 K8S Deployment name |
服务描述 | Nginx部署 | 显示在微服务分层架构图中便于识别的名字,可以是中文 |
副本数量 | 1 | replicas |
容器名称 | nginx | |
镜像 | nginx:1.7.9 | |
抓取策略 | Always | 每次创建 Pod 都尝试抓取镜像 |
Ports | TCP : 80 | 该容器组监听 TCP 80 端口 |
点击 保存 点击 应用 点击 完成
点击 代理 按钮,可以直接测试部署结果。更多细节请参考 Kuboard Proxy, 此功能要求 Kuboard 版本不低于 v1.0.9.4
。
实战:故障排除
在部署第一个应用程序 中,我们使用了 kubectl 命令行界面部署了 nginx 并且查看了 Deployment 和 Pod。kubectl 还有如下四个常用命令,在我们排查问题时可以提供帮助:
- kubectl get - 显示资源列表
#kubectl get 资源类型
#获取类型为Deployment的资源列表
kubectl get deployments
#获取类型为Pod的资源列表
kubectl get pods
#获取类型为Node的资源列表
kubectl get nodes
名称空间
在命令后增加 -A
或 --all-namespaces
可查看所有 名称空间中 的对象,使用参数 -n
可查看指定名称空间的对象,例如
# 查看所有名称空间的 Deployment
kubectl get deployments -A
kubectl get deployments --all-namespaces
# 查看 kube-system 名称空间的 Deployment
kubectl get deployments -n kube-system
- kubectl describe - 显示有关资源的详细信息
# kubectl describe 资源类型 资源名称
#查看名称为nginx-XXXXXX的Pod的信息
kubectl describe pod nginx-XXXXXX
#查看名称为nginx的Deployment的信息
kubectl describe deployment nginx
- kubectl logs - 查看pod中的容器的打印日志(和命令docker logs 类似)
# kubectl logs Pod名称
#查看名称为nginx-pod-XXXXXXX的Pod内的容器打印的日志
#本案例中的 nginx-pod 没有输出日志,所以您看到的结果是空的
kubectl logs -f nginx-pod-XXXXXXX
- kubectl exec - 在pod中的容器环境内执行命令(和命令docker exec 类似)
# kubectl exec Pod名称 操作命令
# 在名称为nginx-pod-xxxxxx的Pod中运行bash
kubectl exec -it nginx-pod-xxxxxx /bin/bash
请尝试在您的集群中执行一下上述的几个命令,了解如何通过 kubectl 操作 kubernetes 集群中的 Node、Pod、Container。
TIP:Worker节点是k8s中的工作计算机,可能是VM或物理计算机,具体取决于群集。多个Pod可以在一个节点上运行。
实战:为您的 nginx Deployment 创建一个 Service
Kubernetes Service(服务)
Kubernetes 中的 Service(服务) 提供了一个抽象层,它选择具备某些特征的 Pod(容器组)并为它们定义一个访问方式。Service(服务)使 Pod(容器组)之间的相互依赖解耦(原本从一个 Pod 中访问另外一个 Pod,需要知道对方的 IP 地址)。一个 Service(服务)选定哪些 Pod(容器组) 通常由 LabelSelector(标签选择器) 来决定。
创建nginx的Deployment中定义了Labels,如下:
metadata: #译名为元数据,即Deployment的一些基本属性和信息
name: nginx-deployment #Deployment的名称
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组
app: nginx #为该Deployment设置key为app,value为nginx的标签
创建文件 nginx-service.yaml
vim nginx-service.yaml
文件内容如下:
apiVersion: v1
kind: Service
metadata:
name: nginx-service #Service 的名称
labels: #Service 自己的标签
app: nginx #为该 Service 设置 key 为 app,value 为 nginx 的标签
spec: #这是关于该 Service 的定义,描述了 Service 如何选择 Pod,如何被访问
selector: #标签选择器
app: nginx #选择包含标签 app:nginx 的 Pod
ports:
- name: nginx-port #端口的名字
protocol: TCP #协议类型 TCP/UDP
port: 80 #集群内的其他容器组可通过 80 端口访问 Service
nodePort: 32600 #通过任意节点的 32600 端口访问 Service
targetPort: 80 #将请求转发到匹配 Pod 的 80 端口
type: NodePort #Serive的类型,ClusterIP/NodePort/LoaderBalancer
执行命令
kubectl apply -f nginx-service.yaml
检查执行结果
kubectl get services -o wide
可查看到名称为 nginx-service 的服务。
访问服务
curl <任意节点的 IP>:32600
如果您的集群在云上,您可能通过云服务商的安全组开放 32600 端口的访问