目录

kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,伴随Kubernetes每个版本的发布都会同步更新,kubeadm会对集群配置方面的一些实践做调整,通过实验kubeadm可以学习到Kubernetes官方在集群配置上一些新的最佳实践。

在Kubernetes的文档Creating a single master cluster with kubeadm中已经给出了目前kubeadm的主要特性已经处于beta状态了,在2018年将进入GA状态,说明kubeadm离可以在生产环境中使用的距离越来越近了。

下面我将介绍一下kubeadm的安装,比起k8s的二进制安装方式,kubeadm的安装门槛较低,更容易上手。

1. 准备工作

1.1 机器准备

准备三台Centos7.x虚拟机,具体配置如下:

IP Role CPU Memory Hostname
192.168.199.231 master >= 2C >= 2G master
192.168.199.232 worker >= 2C >= 2G node1
192.168.199.233 worker >= 2C >= 2G node1

IP 根据你自己宿主机机器网段决定。

1.2 系统配置

1.2.1 主机名及域名解析

# 192.168.199.231上执行
hostnamectl set-hostname master # 192.168.199.232上执行
hostnamectl set-hostname node1 # 192.168.199.233上执行
hostnamectl set-hostname node2 # 192.168.199.231、192.168.199.232、192.168.199.233三台都执行
cat <<EOF>>/etc/hosts
192.168.199.231 master
192.168.199.232 node1
192.168.199.233 node2
EOF

设置完后,相互ping一下看看网络是否通。如:ping node1

1.2.2 免密登录

设置 master 可以无密码登录所有节点的 root 账户:

## 第一步:在master节点执行,一路回车到底
ssh-keygen -t rsa ## 第二步:在master节点执行以下三句,然后分别输入对应机器登录密码
ssh-copy-id root@master
ssh-copy-id root@node1
ssh-copy-id root@node2

1.2.3 配置yum源

注意:所有虚拟机都需要执行下面的操作

配置阿里软件源(base和epel):

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

最后一句记得回车,配置完过后,可通过命令:

yum repolist

来查看是否配置成功。如果出现如下信息则表示成功:

  • base: mirrors.aliyun.com
  • extras: mirrors.aliyun.com
  • updates: mirrors.aliyun.com

配置国内Kubernetes源:

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

配置docker源:

wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

执行清理和更新:

yum clean all && yum makecache && yum update -y	# 第一次需要比较久的时间,去喝杯水休息休息

1.2.4 安装必要依赖包

在三台机器上执行命令:

yum install -y epel-release
yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget
/usr/sbin/modprobe ip_vs # 这一句记得回车

ipvs 依赖 ipset

ntp 保证各机器系统时间同步;

1.2.5 关闭防火墙、SELinux、Swap分区

注意:所有虚拟机都需要执行下面的操作

关闭防火墙:

systemctl stop firewalld &&
systemctl disable firewalld &&
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat &&
iptables -P FORWARD ACCEPT

关闭SELinux:

setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

关闭Swap分区:

swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

1.2.6 配置内核参数

注意:所有虚拟机都需要执行下面的操作

将桥接的IPv4流量传递到iptables的链,swappiness参数调整:

cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.overcommit_memory=1 # 不检查物理内存是否够用
vm.panic_on_oom=0 # 开启 OOM
EOF
modprobe ip_vs_rr
modprobe br_netfilter
sysctl --system # 记得回车

2. 安装Docker

2.1 安装

Kubernetes从1.6开始使用CRI(Container Runtime Interface)容器运行时接口。默认的容器运行时仍然是Docker,使用的是kubelet中内置dockershim CRI实现。

查看版本:

# 查看docker版本
yum list docker-ce.x86_64 --showduplicates | sort -r # 查看docker cli版本
yum list docker-ce-cli.x86_64 --showduplicates |sort -r

Kubernetes 1.15已经针对Docker的1.13.1, 17.03, 17.06, 17.09, 18.06,18.09等版本做了验证,需要注意Kubernetes 1.15最低支持的Docker版本是1.13.1。 我们这里在各节点安装docker的19.03.9版本。

# 安装docker、docker-cli
yum install -y docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7 # 开机启动 && 启动docker
systemctl enable docker && systemctl start docker # 查看版本
docker --version

安装docker还可以通过脚本,详情见:https://leisure.wang/procedural-framework/docker/112.html

2.2 配置镜像加速

# 第一步:创建目录(不存在则创建)
mkdir -p /etc/docker # 第二步:创建并配置daemon.json文件
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"https://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "5"
}
}
EOF # 第三步:重新加载配置并重启docker
systemctl daemon-reload && systemctl restart docker

确认一下iptables filter表中FOWARD链的默认策略(pllicy)为ACCEPT:

# 命令
iptables -nvL # 结果部分如下:
Chain INPUT (policy ACCEPT 321 packets, 18442 bytes)
pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0

3. 使用kubeadm部署k8s集群

3.1 安装kubeadm、kubelet、kubectl

需要在每台机器上都安装以下的软件包:

  • Kubelet:负责与其他节点集群通信,并进行本节点Pod和容器生命周期的管理。
  • Kubeadm:是Kubernetes的自动化部署工具,降低了部署难度,提高效率。
  • Kubectl:是Kubernetes集群管理工具。

查看可用版本:

yum list --showduplicates | grep 'kubeadm\|kubectl\|kubelet'

选择安装kubeadm1.18.0、kubelet1.18.0、kubectl1.18.0

# 安装
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0 --disableexcludes=kubernetes # 此时还不能启动kubelet,先设置开机启动
systemctl enable --now kubelet

从安装结果可以看出还安装了cri-tools, kubernetes-cni, socat三个依赖:

  • socat是kubelet的依赖
  • cri-tools是CRI(Container Runtime Interface)容器运行时接口的命令行工具

运行kubelet –help可以看到原来kubelet的绝大多数命令行flag参数都被DEPRECATED了。

而官方推荐我们使用–config指定配置文件,并在配置文件中指定原来这些flag所配置的内容。具体内容可以查看这里Set Kubelet parameters via a config file。这也是Kubernetes为了支持动态Kubelet配置(Dynamic Kubelet Configuration)才这么做的,参考Reconfigure a Node’s Kubelet in a Live Cluster

kubelet的配置文件必须是json或yaml格式,具体可查看这里

3.2 配置kubeadm

查看kubelet安装了哪些文件:

# 命令
rpm -ql kubelet # 结果
/etc/kubernetes/manifests # 清单目录
/etc/sysconfig/kubelet # 配置文件
/usr/bin/kubelet # 主程序
/usr/lib/systemd/system/kubelet.service # unit file

在所有虚拟机上修改/etc/sysconfig/kubelet,加入:

# 命令
sed -i "s/KUBELET_EXTRA_ARGS=/KUBELET_EXTRA_ARGS=\"--fail-swap-on=false\"/" /etc/sysconfig/kubelet # 查看是否修改
cat /etc/sysconfig/kubelet # 查看结果
KUBELET_EXTRA_ARGS="--fail-swap-on=false"

安装 kubernetes 主要是安装它的各个镜像,而 kubeadm 已经为我们集成好了运行 kubernetes 所需的基本镜像。但由于国内的网络原因,在搭建环境时,无法拉取到这些镜像。此时我们只需要修改为阿里云提供的镜像服务即可解决该问题。

导出配置文件(未修改文件,不可用):

kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml

针对kubeadm.yml文件做修改,新增修改处有4个,如下注释位置,做相应修改即可:

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.199.231 # 修改项,更改为master节点IP
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: master
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: "" # 新增项
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers # 修改项,修改为阿里云镜像仓库
kind: ClusterConfiguration
kubernetesVersion: v1.18.0
networking:
dnsDomain: cluster.local
podSubnet: "10.244.0.0/16" # 新增项,配置Flannel的默认网段
serviceSubnet: 10.96.0.0/12
scheduler: {}
---
# 新增项start:开启IPVS模式
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
SupportIPVSProxyMode: true
mode: ipvs
# 新增项end:开启IPVS模式

配置修改好后,将配置文件复制到node1、node2备用:

scp kubeadm.yml root@node1:/root
scp kubeadm.yml root@node2:/root

查看和拉取镜像:

# 查看所需镜像列表
kubeadm config images list --config kubeadm.yml
# 拉取镜像 (所有机器都执行)
kubeadm config images pull --config kubeadm.yml
# 执行完毕后,通过命令就可以看到镜像了:
docker images

3.3 使用kubeadm 配置master 节点

注意:在master执行下面的操作

3.3.1 安装 kubernetes 主节点

执行以下命令初始化主节点,该命令指定了初始化时需要使用的配置文件,其中添加 --experimental-upload-certs 参数可以在后续执行加入节点时自动分发证书文件。追加的 tee kubeadm-init.log 用以输出日志。

# 初始化命令
kubeadm init --config=kubeadm.yml --upload-certs | tee kubeadm-init.log # 成功则返回如下信息:
Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: 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: kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

node1、node2想要加入集群,需要执行上一步返回结果中的命令:

kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

--token:加入集群的token

--discovery-token-ca-cert-hash:发现token证书hash

此时还无法通过命令kubectl get nodes查看节点信息,需要等下面的配置。

如果忘记了加入集群的命令怎么办呢?通过下面两个方法获取token和discovery-token-ca-cert-hash,然后按照上面的命令的格式拼接起来即可。

获取Token,可以在 Master 上输入以下命令查看:

 kubeadm token list

默认情况下 Token 过期是时间是24小时,如果 Token 过期以后,可以输入以下命令,生成新的 Token:

kubeadm token create

获取discovery-token-ca-cert-hash 的方法,在 Master 运行以下命令查看:

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

注意:如果安装 kubernetes 版本和下载的镜像版本不统一则会出现 timed out waiting for the condition 错误。中途失败或是想修改配置可以使用 kubeadm reset 命令重置配置,再做初始化操作即可。

3.3.2 配置 kubectl

执行初始化集群时候输出结果中的命令:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# 非root用户执行
sudo chown $(id -u):$(id -g) $HOME/.kube/config

验证是否成功:

# 命令
kubectl get nodes # 结果
NAME STATUS ROLES AGE VERSION
master NotReady master 18m v1.18.0
node1 NotReady <none> 14m v1.18.0
node2 NotReady <none> 14m v1.18.0

至此主机诶单配置完成。

3.3.3 kubeadm init执行过程

  • init:指定版本进行初始化操作
  • preflight:初始化前的检查和下载所需要的 Docker 镜像文件
  • kubelet-start:生成 kubelet 的配置文件 var/lib/kubelet/config.yaml,没有这个文件 kubelet 无法启动,所以初始化之前的 kubelet 实际上启动不会成功
  • certificates:生成 Kubernetes 使用的证书,存放在 /etc/kubernetes/pki 目录中
  • kubeconfig:生成 KubeConfig 文件,存放在 /etc/kubernetes 目录中,组件之间通信需要使用对应文件
  • control-plane:使用 /etc/kubernetes/manifest 目录下的 YAML 文件,安装 Master 组件
  • etcd:使用 /etc/kubernetes/manifest/etcd.yaml 安装 Etcd 服务
  • wait-control-plane:等待 control-plan 部署的 Master 组件启动
  • apiclient:检查 Master 组件服务状态。
  • uploadconfig:更新配置
  • kubelet:使用 configMap 配置 kubelet
  • patchnode:更新 CNI 信息到 Node 上,通过注释的方式记录
  • mark-control-plane:为当前节点打标签,打了角色 Master,和不可调度标签,这样默认就不会使用 Master 节点来运行 Pod
  • bootstrap-token:生成 token 记录下来,后边使用 kubeadm join 往集群中添加节点时会用到
  • addons:安装附加组件 CoreDNS 和 kube-proxy

3.4 使用kubeadm配置 worker 节点

3.4.1 将worker加入到集群

将 worker节点加入到集群中很简单,上一步也做了介绍,只需要执行init返回结果中的命令:

kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

3.4.2 验证是否成功

在master节点上运行:

# 命令
kubectl get cs,nodes # 结果
NAME STATUS MESSAGE ERROR
componentstatus/scheduler Healthy ok
componentstatus/controller-manager Healthy ok
componentstatus/etcd-0 Healthy {"health":"true"} NAME STATUS ROLES AGE VERSION
node/master NotReady master 84m v1.18.0
node/node1 NotReady <none> 80m v1.18.0
node/node2 NotReady <none> 79m v1.18.0

如果 worker节点加入 master 时配置有问题可以在 worker节点上使用 kubeadm reset 重置配置再使用 kubeadm join 命令重新加入即可。希望在 master 节点删除 node ,可以使用 kubeadm delete nodes 删除。

3.4.3 查看 pod 状态

# 在master上运行
kubectl get pod -n kube-system -o wide # 结果
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-7ff77c879f-k94rw 0/1 Pending 0 86m <none> <none> <none> <none>
coredns-7ff77c879f-whhdf 0/1 Pending 0 86m <none> <none> <none> <none>
etcd-master 1/1 Running 0 86m 192.168.199.231 master <none> <none>
kube-apiserver-master 1/1 Running 0 86m 192.168.199.231 master <none> <none>
kube-controller-manager-master 1/1 Running 0 86m 192.168.199.231 master <none> <none>
kube-proxy-8jvj5 1/1 Running 1 86m 192.168.199.231 master <none> <none>
kube-proxy-hm8cx 1/1 Running 1 82m 192.168.199.232 node1 <none> <none>
kube-proxy-psnc9 1/1 Running 1 82m 192.168.199.233 node2 <none> <none>
kube-scheduler-master 1/1 Running 0 86m 192.168.199.231 master <none> <none>

由此可以看出 coredns 尚未运行,此时我们还需要安装网络插件。

3.5 配置网络

Kubernetes 中可选的 CNI 插件如下:

  • Flannel
  • Calico
  • Canal
  • Weave

3.5.1 安装flannel网络

# 下载kube-flannel.yml文件,如果无法下载请在附件中获取。
curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 安装
kubectl apply -f kube-flannel.yml

3.5.2 配置网卡名称(可选)

如果Node有多个网卡的话,参考flannel issues 39701,目前需要在kube-flannel.yml中使用–iface参数指定集群主机内网网卡的名称,否则可能会出现dns无法解析。需要将kube-flannel.yml下载到本地,flanneld启动参数加上–iface=,网卡名称可通过ip address命令获取,格式为ensXX

# 部分内容
......
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.11.0-amd64
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=ens32
......

3.5.3 查看Pod状态

使用kubectl get pod –all-namespaces -o wide确保所有的Pod都处于Running状态:

# 命令
watch kubectl get pod --all-namespaces -o wide
# 结果(需要等待所有状态为Running,时间可能需要3-5分钟)
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-7ff77c879f-k94rw 1/1 Running 0 126m 10.244.0.3 master <none> <none>
kube-system coredns-7ff77c879f-whhdf 1/1 Running 0 126m 10.244.0.2 master <none> <none>
kube-system etcd-master 1/1 Running 0 126m 192.168.199.231 master <none> <none>
kube-system kube-apiserver-master 1/1 Running 0 126m 192.168.199.231 master <none> <none>
kube-system kube-controller-manager-master 1/1 Running 0 126m 192.168.199.231 master <none> <none>
kube-system kube-flannel-ds-amd64-6rcjk 1/1 Running 0 15m 192.168.199.231 master <none> <none>
kube-system kube-flannel-ds-amd64-n464m 1/1 Running 0 15m 192.168.199.232 node1 <none> <none>
kube-system kube-flannel-ds-amd64-rlghv 1/1 Running 0 15m 192.168.199.233 node2 <none> <none>
kube-system kube-proxy-8jvj5 1/1 Running 1 126m 192.168.199.231 master <none> <none>
kube-system kube-proxy-hm8cx 1/1 Running 1 122m 192.168.199.232 node1 <none> <none>
kube-system kube-proxy-psnc9 1/1 Running 1 121m 192.168.199.233 node2 <none> <none>
kube-system kube-scheduler-master 1/1 Running 0 126m 192.168.199.231 master <none> <none>

至此基本环节已经部署完毕,如果没有问题,就可以展开k8s的学习之旅了。

3.5.4 问题处理(可选)

3.5.4.1 解决 ImagePullBackOff

在使用 watch kubectl get pods --all-namespaces 命令观察 Pods 状态时如果出现 ImagePullBackOff 无法 Running 的情况,请尝试使用如下步骤处理:

  • Master 中删除 Nodes:kubectl delete nodes
  • worker中重置配置:kubeadm reset
  • worker重启计算机:reboot
  • worker重新加入集群:kubeadm join
3.5.4.2 Master节点参与工作负载

出于安全原因,您的群集不会在主服务器上安排pod。如果您希望能够在主服务器上安排pod,例如对于用于开发的单机Kubernetes集群,可以运行以下命令:

# 所有主服务器都安排 pod
kubectl taint nodes --all node-role.kubernetes.io/master- # 指定节点 master 服务器都安排 pod
kubectl taint nodes <master-hostname> node-role.kubernetes.io/master-
如:kubectl taint nodes master node-role.kubernetes.io/master-

3.6 验证集群DNS是否可用

3.6.1 新建文件my-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
app: my-nginx
replicas: 2
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:1.7.9
ports:
- containerPort: 80

3.6.2 创建Deployment并生成my-nginx服务

# 创建Deployment
kubectl create -f my-nginx.yaml # 查看Deployment
kubectl get deploy # 生成服务
kubectl expose deploy my-nginx # 查看服务
kubectl get services(或 kubectl get svc)
# 结果
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h2m
my-nginx ClusterIP 10.110.206.225 <none> 80/TCP 7m34s

3.6.3 创建dnsutils-ds.yml文件

创建另一个 Pod,查看 /etc/resolv.conf 是否包含 kubelet 配置的 --cluster-dns 和 --cluster-domain,是否能够将服务 my-nginx 解析到对应的 Cluster IP 10.110.206.225

apiVersion: v1
kind: Service
metadata:
name: dnsutils-ds
labels:
app: dnsutils-ds
spec:
type: NodePort
selector:
app: dnsutils-ds
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: dnsutils-ds
labels:
addonmanager.kubernetes.io/mode: Reconcile
spec:
selector:
matchLabels:
app: dnsutils-ds
template:
metadata:
labels:
app: dnsutils-ds
spec:
containers:
- name: my-dnsutils
image: tutum/dnsutils:latest
command:
- sleep
- "3600"
ports:
- containerPort: 80

3.6.4 创建pod dnsutils-ds

kubectl create -f dnsutils-ds.yml

3.6.5 查看pod节点

# 命令
kubectl get pods # 结果
NAME READY STATUS RESTARTS AGE
curl 0/1 CrashLoopBackOff 13 46m
dnsutils-ds-2xgtq 1/1 Running 0 103s
dnsutils-ds-dvzjm 1/1 Running 0 103s
dnsutils-ds-xtsvz 1/1 Running 0 103s
my-nginx-5c7d476867-sqpjv 1/1 Running 0 19m
my-nginx-5c7d476867-vv57z 1/1 Running 0 19m

3.6.6 开始验证DNS

# 命令
kubectl exec dnsutils-ds-2xgtq -- nslookup my-nginx # 结果
Server: 10.96.0.10
Address: 10.96.0.10#53 Name: my-nginx.default.svc.cluster.local
Address: 10.110.206.225

从结果看Address: 10.110.206.225已经成功了。

另外,解析外部域名时,需要以 . 结尾:

# 命令
kubectl exec dnsutils-ds-2xgtq -- nslookup leisure.wang. # 结果
Server: 10.96.0.10
Address: 10.96.0.10#53 Non-authoritative answer:
Name: leisure.wang
Address: 121.36.158.21

3.7 从集群中删除Node

如果需要从集群中移除node2这个Node执行下面的命令:

在master节点上执行:

kubectl drain node2 --delete-local-data --force --ignore-daemonsets
kubectl delete node node2

在 Node 被删除,需要重启所有 kubeadm 安装状态:

kubeadm reset
# 如果要完全删除,请执行下面的清理命令
ifconfig cni0 down
ip link delete cni0
ifconfig flannel.1 down
ip link delete flannel.1
rm -rf /var/lib/cni/

3.8 解决apiserver访问时匿名用户禁用问题

浏览器访问 kube-apiserver 的安全端口 6443 时,提示:

{
"kind": "Status",
"apiVersion": "v1",
"metadata": { },
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
"reason": "Forbidden",
"details": { },
"code": 403
}

对于正式环境,需要创建一个用户并授权,在上面二进制二进制安装里介绍过,多少还是烦了点。

对于学习环境,我们不需要那么麻烦,不就是匿名用户被禁用了吗,直接给匿名用户授权就可以了。

解决办法:绑定一个cluster-admin的权限

kubectl create clusterrolebinding system:anonymous   --clusterrole=cluster-admin   --user=system:anonymous

4. 部署whoami

whoami 是一个简单的HTTP docker服务,用于打印容器ID

在 Master 运行部署 Whoami:

kubectl create deployment whoami --image=idoall/whoami

查看 Whoami 部署状态:

kubectl get deployments

查看 Whoami 的部署信息:

kubectl describe deployment whoami

查看 Whoami 的pod信息:

kubectl describe pod whoami

为 Whoami 扩展端口;创建一个可以通过互联网访问的 Whoami 容器:

kubectl create service nodeport whoami --tcp=80:80

[本文由https://leisure.wang/整理提供]

上面的命令将在主机上为 Whoami 部署创建面向公众的服务。

由于这是一个节点端口部署,因此 kubernetes 会将此服务分配给32000+范围内的主机上的端口。

查看当前的服务状态:

# 命令
kubectl get svc,pods -o wide # 结果
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/dnsutils-ds NodePort 10.97.94.13 <none> 80:30157/TCP 37m app=dnsutils-ds
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h45m <none>
service/my-nginx ClusterIP 10.110.206.225 <none> 80/TCP 51m app=my-nginx
service/whoami NodePort 10.108.27.255 <none> 80:32729/TCP 29s app=whoami NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/curl 0/1 CrashLoopBackOff 20 82m 10.244.1.2 node1 <none> <none>
pod/dnsutils-ds-2xgtq 1/1 Running 0 37m 10.244.1.4 node1 <none> <none>
pod/dnsutils-ds-dvzjm 1/1 Running 0 37m 10.244.0.4 master <none> <none>
pod/dnsutils-ds-xtsvz 1/1 Running 0 37m 10.244.2.3 node2 <none> <none>
pod/my-nginx-5c7d476867-sqpjv 1/1 Running 0 55m 10.244.1.3 node1 <none> <none>
pod/my-nginx-5c7d476867-vv57z 1/1 Running 0 55m 10.244.2.2 node2 <none> <none>
pod/whoami-7976c8ddf6-9lbcp 1/1 Running 0 5m13s 10.244.2.4 node2 <none> <none>

上面的服务可以看到 Whoami 运行在 32729 端口。

测试 Whoami 服务是否运行正常:

# 命令
curl node1:32729 # 结果
[mshk.top]I'm whoami-7976c8ddf6-9lbcp

扩展部署应用:

kubectl scale --replicas=3 deployment/whoami

查看扩展后的结果,可以看到 Whoami 在 master、node1、node2上面都有部署

ClusterIP 模式会提供一个集群内部的虚拟IP(与Pod不在同一网段),以供集群内部的 Pod 之间通信使用。

删除 Whoami 部署:

kubectl delete deployment whoami
kubectl delete service whoami

5. 部署Dashboard

Kubernetes Dashboard 是 Kubernetes 集群的 Web UI,用于管理集群。

5.1 安装

注:在master节点上进行如下操作

5.1.0 下载配置文件

由于网络原因,可能无法下载,无法下载则请直接使用5.1.1文件内容

wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

如果下载成功,请参照5.1.1做如下修改:

  1. 修改镜像地址为阿里云
  2. 修改类型为 NodePort 访问(无type则新增)
  3. 设置端口号为 30001

5.1.1 创建文件kubernetes-dashboard.yaml

apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kube-system
type: Opaque
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kubernetes-dashboard-minimal
namespace: kube-system
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["create"]
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
verbs: ["get", "update", "delete"]
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard-minimal
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kube-system
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: registry.aliyuncs.com/google_containers/kubernetes-dashboard-amd64:v1.10.1 # 修改镜像地址为阿里云
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort # 修改类型为 NodePort 访问(无type则新增)
ports:
- port: 443
targetPort: 8443
nodePort: 30001 # 设置端口号为 30001
selector:
k8s-app: kubernetes-dashboard

5.1.2 部署

kubectl create -f kubernetes-dashboard.yaml

5.1.3 查看

kubectl -n kube-system get pods
kubectl -n kube-system get service kubernetes-dashboard
kubectl -n kube-system describe service kubernetes-dashboard

5.2 访问

需要使用 NodeIP:30001(如:https://192.168.199.231:30001/) 访问 Dashboard,因为证书原因除火狐浏览器外其它浏览器无法直接打开页面。

作为学习,暂时可以不用在意这些细节。访问后,在火狐里点击高级>接受风险并继续。

此时将会看到“Kubernetes 仪表板”。

5.3 登录

5.3.1 kubeconfig方式

该config文件位置一般是 ~/.kube/config(Master节点),只要将该文件下载到本地机器上,登录的时候选择它就行了。

5.3.2 令牌方式

创建访问Dashboard的token,需要创建一个 Admin 用户并授予 Admin 角色绑定,使用下面的 yaml文件 创建 admin 用户并赋予管理员权限,然后可以通过 Token 访问 kubernetes。

创建 kubernetes-dashboard-admin.yaml 文件:

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
labels:
k8s-app: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kube-system

执行部署:

kubectl apply -f kubernetes-dashboard-admin.yaml

获取secret中的token值:

kubectl get secret -o wide --all-namespaces | grep kubernetes-dashboard-token
# 记得替换成你自己的secret资源名
kubectl -n kube-system describe secret kubernetes-dashboard-token-bsjtr

也可以通过 jsonpath 直接获取 token:

kubectl -n kube-system get secret kubernetes-dashboard-token-bsjtr -o jsonpath={.data.token}|base64 -d

也可以使用下面的命令,直接获取 kubernetes-dashboard-token 的值,然后直接打印输出:

k8tokenvalue=`kubectl get secret -o wide --all-namespaces | grep kubernetes-dashboard-token | awk '{print $2}'`;kubectl -n kube-system get secret $k8tokenvalue -o jsonpath={.data.token}|base64 -d | awk '{print $1}'

注意:下面的获取token值的方式和上面三种方式选择一种即可。

您还可以通过kubectl create clusterrolebinding的方式来授予 Dashboard 服务 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}')

登录成功后就能看到后台页面了:

6. Weave Scope 监控集群

创建 Kubernetes 集群并部署容器化应用只是第一步。一旦集群运行起来,我们需要确保一起正常,所有必要组件就位并各司其职,有足够的资源满足应用的需求。Kubernetes 是一个复杂系统,运维团队需要有一套工具帮助他们获知集群的实时状态,并为故障排查提供及时和准确的数据支持。

6.1 安装

Weave Scope 是 Docker 和 Kubernetes 可视化监控工具。Scope 提供了至上而下的集群基础设施和应用的完整视图,用户可以轻松对分布式的容器化应用进行实时监控和问题诊断。

在 K8s 集群中安装 Scope 的方法很简单,使用下面的命令:

# 命令
kubectl apply -f "https://cloud.weave.works/k8s/scope.yaml?k8s-version=$(kubectl version | base64 | tr -d '\n')&k8s-service-type=NodePort" # 结果
service-type=NodePort"
namespace/weave created
serviceaccount/weave-scope created
clusterrole.rbac.authorization.k8s.io/weave-scope created
clusterrolebinding.rbac.authorization.k8s.io/weave-scope created
deployment.apps/weave-scope-app created
service/weave-scope-app created
deployment.apps/weave-scope-cluster-agent created
daemonset.apps/weave-scope-agent created

部署成功后有如下组件:

# 命令
kubectl get pod -n weave
# 结果
NAME READY STATUS RESTARTS AGE
weave-scope-agent-2t7z2 0/1 ContainerCreating 0 60s
weave-scope-agent-ll9r9 0/1 ContainerCreating 0 60s
weave-scope-agent-qzp2b 0/1 ContainerCreating 0 60s
weave-scope-app-bc7444d59-lznk8 0/1 ContainerCreating 0 62s
weave-scope-cluster-agent-7944c858c9-ms7mz 0/1 ContainerCreating 0 61s # 命令
kubectl get svc -n weave
# 结果
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
weave-scope-app NodePort 10.108.61.84 <none> 80:30286/TCP 3m9s # 命令
kubectl get deploy -n weave
# 结果
NAME READY UP-TO-DATE AVAILABLE AGE
weave-scope-app 1/1 1 1 4m19s
weave-scope-cluster-agent 1/1 1 1 4m18s
  • DaemonSet weave-scope-agent,集群每个节点上都会运行的 scope agent 程序,负责收集数据。
  • Deployment weave-scope-app,scope 应用,从 agent 获取数据,通过 Web UI 展示并与用户交互。
  • Service weave-scope-app,默认是 ClusterIP 类型,我们已经在上面的命令中添加了参数k8s-service-type=NodePort修改为 NodePort。

6.2 使用Scope

浏览器访问http://MASTER_IP:30286/(端口可在上一步查看命令中获得),cope 默认显示当前所有的 Controller(Deployment、DaemonSet 等)。

6.2.1 拓扑结构

Scope 会自动构建应用和集群的逻辑拓扑。比如点击顶部 Pods,会显示所有 Pod 以及 Pod 之间的依赖关系。

点击 Hosts,会显示各个节点之间的关系,可以在 Scope 中查看资源的 CPU 和内存使用情况。

6.2.2 在线操作

Scope 还提供了便捷的在线操作功能,比如选中某个 Host,点击 >_ 按钮可以直接在浏览器中打开节点的命令行终端:

点击 Deployment 的 + 可以执行 Scale Up 操作:

可以查看 Pod 的日志:

可以 attach、restart、stop 容器,以及直接在 Scope 中排查问题:

6.2.3 强大的搜索功能

Scope 支持关键字搜索和定位资源。

还可以进行条件搜索,比如查找和定位 MEMORY > 1M 的 Containers。

Weave Scope 界面极其友好,操作简洁流畅,更多功能留给大家去探索。

官方文档:https://www.weave.works/docs/scope/latest/installing/#k8s

写在最后

通过kubeadm安装k8s集群环境的介绍就到这里了,书写安装过程难免出现不足的地方,如果出了问题,需要读者多多思考。由于国内网络的原因,文档中所需要的大部分配置文件都已经贴了出来,读者只需要根据自己的机器环境做相应的修改即可。通过kubeadm安装k8s集群环境,相对于二进制的安装方式来说,还是比较简单的,需要多多实践,才能出真知。我是东方雨倾,感谢大家的支持,谢谢!

附件

链接:https://pan.baidu.com/s/1qWdZ_CclTxm2ybE4h8dziA

提取码:ruo5

原文地址:https://leisure.wang/procedural-framework/docker/513.html

还不会K8S吗?先从kubeadm开始吧的更多相关文章

  1. k8s常用指令集(kubectl kubeadm)

    1      Kubectl指令集 1.1      Master查询节点信息 [root@master1 kubernetes-1.10]# kubectl get nodes 1.2      查 ...

  2. k8s踩坑记 - kubeadm join 之 token 失效

    抛砖引玉 环境 centos 7 amd64 两台 kubernetes 1.10 伴随着k8s1.10版本的发布,前天先在一台机器上搭建了k8s单机版集群,即既是master,也是node,按照经验 ...

  3. k8s环境搭建--基于kubeadm方法

    环境 master node: 数量 1, 系统 ubuntu 16.04_amd64 worker node: 数量 1, 系统 ubuntu 16.04_amd64 kubernetes 版本: ...

  4. Kubernetes(K8s) 安装(使用kubeadm安装Kubernetes集群)

    背景: 由于工作发生了一些变动,很长时间没有写博客了. 概述: 这篇文章是为了介绍使用kubeadm安装Kubernetes集群(可以用于生产级别).使用了Centos 7系统. 一.Centos7 ...

  5. [K8s 1.9实践]Kubeadm 1.9 HA 高可用 集群 本地离线镜像部署

    k8s介绍 k8s 发展速度很快,目前很多大的公司容器集群都基于该项目,如京东,腾讯,滴滴,瓜子二手车,北森等等. kubernetes1.9版本发布2017年12月15日,每是那三个月一个迭代, W ...

  6. Kubernetes实战指南(三十三):都0202了,你还在手写k8s的yaml文件?

    目录 1. k8s的yaml文件到底有多复杂 2. 基于图形化的方式自动生成yaml 2.1 k8s图形化管理工具Ratel安装 2.2 使用Ratel创建生成yaml文件 2.2.1 基本配置 2. ...

  7. 使用Kubeadm创建k8s集群之节点部署(三十一)

    前言 本篇部署教程将讲述k8s集群的节点(master和工作节点)部署,请先按照上一篇教程完成节点的准备.本篇教程中的操作全部使用脚本完成,并且对于某些情况(比如镜像拉取问题)还提供了多种解决方案.不 ...

  8. kubeadm部署K8S集群v1.16.3

    本次先更新kubeadm快速安装K8S,二进制安装上次没写文档,后续更新,此次最新的版本是V1.16.3 1.关闭防火墙.关闭selinux.关闭swapoff -a systemctl stop f ...

  9. 使用kubeadm搭建高可用k8s v1.16.3集群

    目录 1.部署环境说明 2.集群架构及部署准备工作 2.1.集群架构说明 2.2.修改hosts及hostname 2.3.其他准备 3.部署keepalived 3.1.安装 3.2.配置 3.3. ...

随机推荐

  1. Java程序员必备基础结构图

    前言 最近看了深入理解Java虚拟机第三版,整理了一些基础结构图,算是比较全的了,做一下笔记,大家一起学习. 1.Java虚拟机运行时数据区图 JVM内存结构是Java程序员必须掌握的基础. 程序计数 ...

  2. Spring.getBean()流程和循环依赖的解决

    getBean流程介绍(以单例的Bean流程为准) getBean(beanName) 从BeanFactory中获取Bean的实例对象,真正获取的逻辑由doGetBean实现. doGetBean( ...

  3. Netty(二):数据在ChannelPipeline中的流经

    本文目的:测试数据在ChannelPipeline中的流经顺序及状态. 先看本文的测试代码: AdditionalInBoundHandler:入站处理器,不做任何处理,只是在响应读事件时打印用来观察 ...

  4. Java pdf转高清图片

    为什么80%的码农都做不了架构师?>>>   package com.hyb.kai.web.controller; import java.awt.image.BufferedIm ...

  5. INTERVIEW #2

    吐槽下ZZ的面试安排:面试时间12:30不说了,周围没有饭店,中午就没吃饭...不像其他公司给每个人安排不同的面试时间,这样可以节约大家的时间,SPDB是把一大批人都安排在了12:30,而且面试是5个 ...

  6. 图论--差分约束--POJ 3169 Layout(超级源汇建图)

    Like everyone else, cows like to stand close to their friends when queuing for feed. FJ has N (2 < ...

  7. 图论--网络流--最大流--POJ 1698 Alice's Chance

    Description Alice, a charming girl, have been dreaming of being a movie star for long. Her chances w ...

  8. POJ - 2387 Til the Cows Come Home (最短路入门)

    Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before ...

  9. python(json 模块)

    1.Json 定义 定义:JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.JSON 的数据格式其实就是 python 里面的字典格式,里 ...

  10. VL01N发货过账无法冲销

    1业务场景 SD和EWM在使用BAPI:BAPI_OUTB_DELIVERY_CONFIRM_DEC发货过账后,发现外向交货单无法被冲销,后来发现是在发货过账后,有一个字段VLSTK声明仓库被维护上了 ...