Kubernetes1.18.5部署,kuboard可视化管理界面,harbor私有仓库的部署,docker与dockerfile创建私有镜像

Kubernetes1.18.5部署,kuboard可视化管理界面,harbor私有仓库的部署,docker创建私有镜像


基本环境准备:

1、部署完成kubernetes1.18集群:
	vm198     192.168.1.198       master与work
	vm193     192.168.1.193       master与work
	vm194    192.168.1.194        master与work
	vm199    192.168.1.199        worker
	vm195    192.168.1.195        nginx反向代理(如果用阿里的SLB可以忽略)
2、修改主机名,关闭防火墙和selinux=Disabled
3、所有主机相互做免密登录
4、centos7.9最小化安装,最低要求2核4G,默认英文,不要用快照做系统
5、配置所有主机/etc/hosts
192.168.1.194    vm194
192.168.1.193    vm193
192.168.1.199    vm199
192.168.1.198    vm198
192.168.1.195    apiserver.demo

(1)最小化centos7.9通过yum安装一些基本工具,关闭selinux和firewalld
vi conf.sh

#!/bin/bash
yum -y install net-tools vim epel-release bash-completion wget yum-plugin-fastestmirror
cat /etc/selinux/config | sed "s/\(SELINUX=enforcing\)/SELINUX=disabled/" > config && mv -f config /etc/selinux/config
setenforce 0
systemctl stop firewalld
systemctl disable firewalld
chmod +x conf.sh
./conf.sh

(2)生成秘钥对
-t:
-N:是指密码为空;
-f:id_rsa是指保存文件为/.ssh/id_rsa和/.ssh/id_rsa.pub
-q:指静默模式, 不输出显示

ssh-keygen -t rsa -N '' -f /root/.ssh/id_rsa -q

所有主机都需要执行:

ssh-copy-id [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]

(3)配置/etc/hosts(所有主机都需要执行)

vim /etc/hosts
192.168.1.194    vm194
192.168.1.193    vm193
192.168.1.199    vm199
192.168.1.198    vm198
192.168.1.195    apiserver.demo

(4)配置ntp时间同步(集群里的所有主机执行)

yum -y install ntpdate
ntpdate ntp1.aliyun.com

kubernetes基本使用命令:

强制删除一个pod
kubectl delete pods  --grace-period=0 --force

强制删除一组coredns,两个一起删除
kubectl delete pod coredns-68b9d7b887-5pd75 coredns-68b9d7b887-wc8qw -n kube-system --grace-period=0 --force

查看所有名称空间
kubectl get namespaces

查看当前所在名称空间
kubectl config current-context

切换名称空间
kubectl config use-context dev

查看所有节点
kubectl get nodes

查看指定名称空间的pod
kubectl get pods  -n  adminprean    #adminprean是名称空间名

创建一个名称空间
kubectl create ns adminprean

进行指定名称空间里的pod
kubectl exec -it  pod的id  -n adminprean   bash  #进行adminprean里的pod

文档说明:

https://kuboard.cn/learning/k8s-intermediate/obj/namespace-op.html#%E5%88%9B%E5%BB%BA%E6%96%B0%E7%9A%84%E5%90%8D%E7%A7%B0%E7%A9%BA%E9%97%B4

一、Kubernetes1.18.5在线部署

1、通过sh脚本安装docker-ce和kubernetes,集群中的所有主机都需要执行
vim /root/install-kubernetes.sh

#!/bin/bash

# 在 master 节点和 worker 节点都要执行

# 安装 docker
# 参考文档如下
# https://docs.docker.com/install/linux/docker-ce/centos/ 
# https://docs.docker.com/install/linux/linux-postinstall/

# 卸载旧版本
yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine

# 设置 yum repository
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装并启动 docker
yum install -y docker-ce-18.09.7 docker-ce-cli-18.09.7 containerd.io
systemctl enable docker
systemctl start docker

# 安装 nfs-utils
# 必须先安装 nfs-utils 才能挂载 nfs 网络存储
yum install -y nfs-utils
yum install -y wget

# 关闭 防火墙
systemctl stop firewalld
systemctl disable firewalld

# 关闭 SeLinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

# 关闭 swap
swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab

# 修改 /etc/sysctl.conf
# 如果有配置,则修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g"  /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g"  /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g"  /etc/sysctl.conf
# 可能没有,追加
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
# 执行命令以应用
sysctl -p

# 配置K8S的yum源
cat < /etc/yum.repos.d/kubernetes.repo
[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
EOF

# 卸载旧版本
yum remove -y kubelet kubeadm kubectl

# 安装kubelet、kubeadm、kubectl
yum install -y kubelet-1.18.5 kubeadm-1.18.5 kubectl-1.18.5

# 修改docker Cgroup Driver为systemd
# # 将/usr/lib/systemd/system/docker.service文件中的这一行 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
# # 修改为 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd
# 如果不修改,在添加 worker 节点时可能会碰到如下错误
# [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". 
# Please follow the guide at https://kubernetes.io/docs/setup/cri/
sed -i "s#^ExecStart=/usr/bin/dockerd.*#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd#g" /usr/lib/systemd/system/docker.service

# 设置 docker 镜像,提高 docker 镜像下载速度和稳定性
# 如果您访问 https://hub.docker.io 速度非常稳定,亦可以跳过这个步骤
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io

# 重启 docker,并启动 kubelet
systemctl daemon-reload
systemctl restart docker
systemctl enable kubelet && systemctl start kubelet

docker version

赋予权限后执行:(集群里的所有主机都需要执行)

chmod +x /root/install-kubernetes.sh
./kubernetes.sh

报错情况处理:
(1)当执行完上面脚本后,kubelet服务有可能是未启动状态,手动启动也会报找不到config.yaml配置文件,这时不用处理,在下面初始化时会创建这个文件,并启动kubelet
(2)在初始化第2、3台时,如果初始化错误,用kuboadm reset重置时,必须删除$HOME/.kube文件夹,否则加入会失败;而且2、3台在执行完上面脚本后kubelet也有可能是未启动状态(手动启动也会失败,也不用处理),在获取第1台的join后,直接在2、3台上执行kubeadm join … 命令加入集群后,kubelet会自动启动,并创建核心模块。

2、初始化API Server

注释:
监听端口:6443 / TCP
后端资源组:包含 demo-master-a-1, demo-master-a-2, demo-master-a-3
后端端口:6443
开启 按源地址保持会话
假设完成创建以后,Load Balancer的 ip 地址为 x.x.x.x
根据每个人实际的情况不同,实现 LoadBalancer 的方式不一样,本文不详细阐述如何搭建 LoadBalancer,请读者自行解决,可以考虑的选择有:
nginx
haproxy
keepalived
云供应商提供的负载均衡产品

(1)这里在本地的vm195上部署一个nginx来实现反向代理:

yum -y install gcc openssl pcre-devel
yum -y install nginx
vim /etc/nginx/nginx.conf   #在http外面添加以下内容
stream {
    server {
        listen 6443;
        proxy_pass k8s_masters;
    }
    upstream k8s_masters {
        server 192.168.1.193:6443;
        server 192.168.1.194:6443;
        server 192.168.1.198:6443;
        #sticky_cookie_insert srv_id expires=1h domain=apiservice.demo path=/;
    }
    }

(2)初始化第一个master节点:
初始化 master 节点时,如果因为中间某些步骤的配置出错,想要重新初始化 master 节点,请先执行 kubeadm reset 操作

vim  /root/initialize-master.sh
# 只在第一个 master 节点执行
# 替换 apiserver.demo 为 您想要的 dnsName
export APISERVER_NAME=apiserver.demo
# Kubernetes 容器组所在的网段,该网段安装完成后,由 kubernetes 创建,事先并不存在于您的物理网络中
export POD_SUBNET=10.100.0.1/16
#下面用的vm195反向代理来定义apiserver.demo
echo "192.168.1.195    ${APISERVER_NAME}" >> /etc/hosts

#!/bin/bash

# 只在 master 节点执行

# 脚本出错时终止执行
set -e

if [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then
  echo -e "\033[31;1m请确保您已经设置了环境变量 POD_SUBNET 和 APISERVER_NAME \033[0m"
  echo 当前POD_SUBNET=$POD_SUBNET
  echo 当前APISERVER_NAME=$APISERVER_NAME
  exit 1
fi


# 查看完整配置选项 https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2
rm -f ./kubeadm-config.yaml
cat < ./kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.5
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "${APISERVER_NAME}:6443"
networking:
  serviceSubnet: "10.96.0.0/16"
  podSubnet: "${POD_SUBNET}"
  dnsDomain: "cluster.local"
EOF

# kubeadm init
# 根据您服务器网速的情况,您需要等候 3 - 10 分钟
kubeadm init --config=kubeadm-config.yaml --upload-certs

# 配置 kubectl
rm -rf /root/.kube/
mkdir /root/.kube/
cp -i /etc/kubernetes/admin.conf /root/.kube/config

# 安装 calico 网络插件
# 参考文档 https://docs.projectcalico.org/v3.9/getting-started/kubernetes/
rm -f calico-3.9.2.yaml
wget https://kuboard.cn/install-script/calico/calico-3.9.2.yaml
sed -i "s#192\.168\.0\.0/16#${POD_SUBNET}#" calico-3.9.2.yaml
kubectl apply -f calico-3.9.2.yaml
chmod +x /root//root/initialize-master.sh
cd /root
./initialize-master.sh

(3)执行结果如下:

第15、16、17行,用于初始化第二、三个 master 节点
第25、26行,用于初始化 worker 节点

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/

You can now join any number of the control-plane node running the following command on each as root:

  kubeadm join apiserver.k8s:6443 --token 4z3r2v.2p43g28ons3b475v \
    --discovery-token-ca-cert-hash sha256:959569cbaaf0cf3fad744f8bd8b798ea9e11eb1e568c15825355879cf4cdc5d6 \
    --control-plane --certificate-key 41a741533a038a936759aff43b5680f0e8c41375614a873ea49fde8944614dd6

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use 
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join apiserver.k8s:6443 --token 4z3r2v.2p43g28ons3b475v \
    --discovery-token-ca-cert-hash sha256:959569cbaaf0cf3fad744f8bd8b798ea9e11eb1e568c15825355879cf4cdc5d6

(4)检查master初始化结果

# 只在第一个 master 节点执行

# 执行如下命令,等待 3-10 分钟,直到所有的容器组处于 Running 状态
watch kubectl get pod -n kube-system -o wide

# 查看 master 节点初始化结果
kubectl get nodes

请等到所有容器组(大约9个)全部处于 Running 状态,才进行下一步

3、初始化第二、三个master节点:两种情况,根据情况选择1种
(1)和第一个Master节点一起初始化(只在第二、三个master上执行)

vim /root/initialize-master.sh
#!/bin/bash
# 只在第二、三个 master 节点 demo-master-b-1 和 demo-master-b-2 执行
# 替换 x.x.x.x 为 ApiServer LoadBalancer 的 IP 地址,这里配置的是192.168.1.195
export APISERVER_IP=192.168.1.195
# 替换 apiserver.demo 为 前面已经使用的 dnsName
export APISERVER_NAME=apiserver.demo
echo "${APISERVER_IP}    ${APISERVER_NAME}" >> /etc/hosts
# 使用前面步骤中获得的第二、三个 master 节点的 join 命令
kubeadm join apiserver.demo:6443 --token ejwx62.vqwog6il5p83uk7y \
--discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303 \
--control-plane --certificate-key 70eb87e62f052d2d5de759969d5b42f372d0ad798f98df38f7fe73efdf63a13c

(2)第一个master节点初始化2个小时后再初始化(与上面任选一种即可)
获得 certificate key
在第一个master上执行:

# 只在 第一个 master 节点 demo-master-a-1 上执行
kubeadm init phase upload-certs --upload-certs

输出结果如下:

kubeadm init phase upload-certs --upload-certs
 
W0902 09:05:28.355623    1046 version.go:98] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get https://dl.k8s.io/release/stable-1.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
W0902 09:05:28.355718    1046 version.go:99] falling back to the local client version: v1.16.2
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
70eb87e62f052d2d5de759969d5b42f372d0ad798f98df38f7fe73efdf63a13c

获得 join 命令

# 只在 第一个 master 节点 demo-master-a-1 上执行
kubeadm token create --print-join-command

输出结果如下:

kubeadm token create --print-join-command
kubeadm join apiserver.demo:6443 --token bl80xo.hfewon9l5jlpmjft     --discovery-token-ca-cert-hash sha256:b4d2bed371fe4603b83e7504051dcfcdebcbdcacd8be27884223c4ccc13059a4 

则,第二、三个 master 节点的 join 命令如下:
命令行中,蓝色部分来自于前面获得的 join 命令,红色部分来自于前面获得的 certificate key

kubeadm join apiserver.demo:6443 --token ejwx62.vqwog6il5p83uk7y \
--discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303 \
--control-plane --certificate-key 70eb87e62f052d2d5de759969d5b42f372d0ad798f98df38f7fe73efdf63a13c

初始化第二、三个 master 节点,只在此两个节点执行:

# 只在第二、三个 master 节点 demo-master-b-1 和 demo-master-b-2 执行

# 替换 x.x.x.x 为 ApiServer LoadBalancer 的 IP 地址,这里是本地的192.168.1.195
export APISERVER_IP=192.168.1.195

# 替换 apiserver.demo 为 前面已经使用的 dnsName
export APISERVER_NAME=apiserver.demo
echo "${APISERVER_IP}    ${APISERVER_NAME}" >> /etc/hosts

# 使用前面步骤中获得的第二、三个 master 节点的 join 命令
kubeadm join apiserver.demo:6443 --token ejwx62.vqwog6il5p83uk7y \
--discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303 \
--control-plane --certificate-key 70eb87e62f052d2d5de759969d5b42f372d0ad798f98df38f7fe73efdf63a13c

4、检查master初始化结果:

# 只在第一个 master 节点 demo-master-a-1 执行
# 查看 master 节点初始化结果
kubectl get nodes

5、拷贝admin.conf到其他master节点,就可以在其他的master节点上使用kubectl了

#在第一个master节点上执行拷贝:
scp -r /etc/kubernetes/admin.conf root@vm194:/etc/kubernetes/admin.conf

#再到vm194上执行下面的命令
echo export KUBECONFIG=/etc/kubernetes/admin.conf  >>  ~/.bash_profile
source ~/.bash_profile
kubectl get nodes

6、常见问题:

(1)如果在初始化master时一定要保证集群时间统一,如果初始化报错:
可以执行kubeadm reset来还原主机的kubelet集群设置,再重新初始化即可。
如下报错:只针对新的k8s集群。

Unable to connect to the server: net/http: TLS handshake timeout

(2)如果一直停留在 pre-flight 状态,请在第二、三个节点上执行命令检查:

curl -ik https://apiserver.demo:6443/version

输出结果应该如下所示:

HTTP/1.1 200 OK
Cache-Control: no-cache, private
Content-Type: application/json
Date: Wed, 30 Oct 2019 08:13:39 GMT
Content-Length: 263

{
  "major": "1",
  "minor": "16",
  "gitVersion": "v1.16.2",
  "gitCommit": "2bd9643cee5b3b3a5ecbd3af49d09018f0773c77",
  "gitTreeState": "clean",
  "buildDate": "2019-09-18T14:27:17Z",
  "goVersion": "go1.12.9",
  "compiler": "gc",
  "platform": "linux/amd64"
}

否则,请您检查一下您的 Loadbalancer 是否设置正确

7、初始化worker节点
这里可以在vm199上执行
获取join命令参数(也是有两种情况,根据本地环境来选择)

(1)和第一个master节点一起初始化
初始化第一个 master 节点时的输出内容中,第25、26行就是用来初始化 worker 节点的命令,如下所示:此时请不要执行该命令

  kubeadm join apiserver.k8s:6443 --token 4z3r2v.2p43g28ons3b475v \
    --discovery-token-ca-cert-hash sha256:959569cbaaf0cf3fad744f8bd8b798ea9e11eb1e568c15825355879cf4cdc5d6

该 token 的有效时间为 2 个小时,2小时内,您可以使用此 token 初始化任意数量的 worker 节点
执行脚本:
vim /root/worker.sh

#!/bin/bash
# 只在 worker 节点执行
# 替换 x.x.x.x 为 ApiServer LoadBalancer 的 IP 地址,这里配置的是192.168.1.195
export MASTER_IP=192.168.1.195
# 替换 apiserver.demo 为初始化 master 节点时所使用的 APISERVER_NAME
export APISERVER_NAME=apiserver.demo
echo "${MASTER_IP}    ${APISERVER_NAME}" >> /etc/hosts

# 替换为前面 kubeadm token create --print-join-command 的输出结果
kubeadm join apiserver.demo:6443 --token mpfjma.4vjjg8flqihor4vt     --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303

(2)第二种情况:第一个master节点初始化2个小时后再初始化(根据实际情况任选1种)

# 只在第一个 master 节点  上执行
kubeadm token create --print-join-command

可获取kubeadm join 命令及参数,如下所示

kubeadm join apiserver.demo:6443 --token mpfjma.4vjjg8flqihor4vt     --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303

该 token 的有效时间为 2 个小时,2小时内,您可以使用此 token 初始化任意数量的 worker 节点。
对所有worker节点执行:
vim /root/worker.sh

#!/bin/bash
# 只在 worker 节点执行
# 替换 x.x.x.x 为 ApiServer LoadBalancer 的 IP 地址
export MASTER_IP=192.168.1.5
# 替换 apiserver.demo 为初始化 master 节点时所使用的 APISERVER_NAME
export APISERVER_NAME=apiserver.demo
echo "${MASTER_IP}    ${APISERVER_NAME}" >> /etc/hosts

# 替换为前面 kubeadm token create --print-join-command 的输出结果
kubeadm join apiserver.demo:6443 --token mpfjma.4vjjg8flqihor4vt     --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303

8、检查worker初始化结果

# 只在第一个 master 节点 demo-master-a-1 上执行
kubectl get nodes

8、移除worker节点
(1)在准备移除的 worker 节点上执行

kubeadm reset

(2)在第一个master节点上执行

kubectl delete node vm199

验证:

kubectl get nodes

二、部署kuboard可视化管理界面

在第一个master里执行:
(1)创建yaml安装文件

cd  /root/
vim install-kuboard.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kuboard
  namespace: kube-system
  annotations:
    k8s.kuboard.cn/displayName: kuboard
    k8s.kuboard.cn/ingress: "true"
    k8s.kuboard.cn/service: NodePort
    k8s.kuboard.cn/workload: kuboard
  labels:
    k8s.kuboard.cn/layer: monitor
    k8s.kuboard.cn/name: kuboard
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s.kuboard.cn/layer: monitor
      k8s.kuboard.cn/name: kuboard
  template:
    metadata:
      labels:
        k8s.kuboard.cn/layer: monitor
        k8s.kuboard.cn/name: kuboard
    spec:
      containers:
      - name: kuboard
        image: eipwork/kuboard:latest
        imagePullPolicy: Always
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
        operator: Exists

---
apiVersion: v1
kind: Service
metadata:
  name: kuboard
  namespace: kube-system
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 32567
  selector:
    k8s.kuboard.cn/layer: monitor
    k8s.kuboard.cn/name: kuboard

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kuboard-user
  namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kuboard-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kuboard-user
  namespace: kube-system

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kuboard-viewer
  namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kuboard-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: view
subjects:
- kind: ServiceAccount
  name: kuboard-viewer
  namespace: kube-system

# ---
# apiVersion: extensions/v1beta1
# kind: Ingress
# metadata:
#   name: kuboard
#   namespace: kube-system
#   annotations:
#     k8s.kuboard.cn/displayName: kuboard
#     k8s.kuboard.cn/workload: kuboard
#     nginx.org/websocket-services: "kuboard"
#     nginx.com/sticky-cookie-services: "serviceName=kuboard srv_id expires=1h path=/"
# spec:
#   rules:
#   - host: kuboard.yourdomain.com
#     http:
#       paths:
#       - path: /
#         backend:
#           serviceName: kuboard
#           servicePort: http
vim  install-metrice-server.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:aggregated-metrics-reader
  labels:
    rbac.authorization.k8s.io/aggregate-to-view: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list", "watch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:metrics-server
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  - nodes/stats
  - namespaces
  verbs:
  - get
  - list
  - watch

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
  
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  name: v1beta1.metrics.k8s.io
spec:
  service:
    name: metrics-server
    namespace: kube-system
    port: 443
  group: metrics.k8s.io
  version: v1beta1
  insecureSkipTLSVerify: true
  groupPriorityMinimum: 100
  versionPriority: 100

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    k8s-app: metrics-server
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
    spec:
      serviceAccountName: metrics-server
      volumes:
      # mount in tmp so we can safely use from-scratch images and/or read-only containers
      - name: tmp-dir
        emptyDir: {}
      hostNetwork: true
      containers:
      - name: metrics-server
        image: eipwork/metrics-server:v0.3.7
        # command:
        # - /metrics-server
        # - --kubelet-insecure-tls
        # - --kubelet-preferred-address-types=InternalIP 
        args:
          - --cert-dir=/tmp
          - --secure-port=4443
          - --kubelet-insecure-tls=true
          - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,externalDNS
        ports:
        - name: main-port
          containerPort: 4443
          protocol: TCP
        securityContext:
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        imagePullPolicy: Always
        volumeMounts:
        - name: tmp-dir
          mountPath: /tmp
      nodeSelector:
        beta.kubernetes.io/os: linux

---
apiVersion: v1
kind: Service
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    kubernetes.io/name: "Metrics-server"
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    k8s-app: metrics-server
  ports:
  - port: 443
    protocol: TCP
    targetPort: 4443

(2)执行安装:

kubectl apply -f install-kuboard.yaml
kubectl apply -f install-metrics-server.yaml

报错情况处理
【1】在创建install-metrics-server.yaml时报如下错误:
0/3 nodes are available: 3 node(s) had taint {node-role.kubernetes. io/master: }, that the pod didn’t tolerate

解决方法:
意思是:1个节点有pod不能容忍的污点{node-role.kubernetes.io/master:}。
原因:当创建单机版的 k8s 时,这个时候 master 节点是默认不允许调度 pod 。
执行以下命令将 master 标记为可调度

kubectl taint nodes --all node-role.kubernetes.io/master-

扩展备注:
Taint(污点)和 Toleration(容忍)可以作用于 node 和 pod 上,其目的是优化 pod 在集群间的调度,这跟节点亲和性类似,只不过它们作用的方式相反,具有 taint 的 node 和 pod 是互斥关系,而具有节点亲和性关系的 node 和 pod 是相吸的。另外还有可以给 node 节点设置 label,通过给 pod 设置 nodeSelector 将 pod 调度到具有匹配标签的节点上。

Taint 和 toleration 相互配合,可以用来避免 pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有相应 taint 的节点上。

设置污点:

NoSchedule: 一定不能被调度
PreferNoSchedule: 尽量不要调度
NoExecute: 不仅不会调度, 还会驱逐Node上已有的Pod
 
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule

(3)查看 Kuboard 运行状态:

kubectl get pods -l k8s.kuboard.cn/name=kuboard -n kube-system

输出结果如下所示:

NAME                       READY   STATUS        RESTARTS   AGE
kuboard-54c9c4f6cb-6lf88   1/1     Running       0          45s

(4)获取token
执行以下命令:

# 如果您参考 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)

输出如下:

eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWc4aHhiIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5NDhiYjVlNi04Y2RjLTExZTktYjY3ZS1mYTE2M2U1ZjdhMGYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.DZ6dMTr8GExo5IH_vCWdB_MDfQaNognjfZKl0E5VW8vUFMVvALwo0BS-6Qsqpfxrlz87oE9yGVCpBYV0D00811bLhHIg-IR_MiBneadcqdQ_TGm_a0Pz0RbIzqJlRPiyMSxk1eXhmayfPn01upPdVCQj6D3vAY77dpcGplu3p5wE6vsNWAvrQ2d_V1KhR03IB1jJZkYwrI8FHCq_5YuzkPfHsgZ9MBQgH-jqqNXs6r8aoUZIbLsYcMHkin2vzRsMy_tjMCI9yXGiOqI-E5efTb-_KbDVwV5cbdqEIegdtYZ2J3mlrFQlmPGYTwFI8Ba9LleSYbCi4o0k74568KcN_w

(5)访问kuboard
通过nodeport访问

Kuboard Service 使用了 NodePort 的方式暴露服务,NodePort 为 32567;您可以按如下方式访问 Kuboard。

http://任意一个Worker节点的IP地址:32567/

输入前一步骤中获得的 token,可进入 Kuboard 集群概览页

如果您使用的是阿里云、腾讯云等,请在其安全组设置里开放 worker 节点 32567 端口的入站访问

您也可以修改 Kuboard.yaml 文件,使用自己定义的 NodePort 端口号

Kubernetes1.18.5部署,kuboard可视化管理界面,harbor私有仓库的部署,docker与dockerfile创建私有镜像_第1张图片

(6)在vm195上配置nginx

vim  /etc/nginx/nginx.conf
# 代理kuboard
server {
    listen 32567;
    proxy_pass k8s_kuboard;
}
upstream k8s_kuboard {
    server 192.168.1.193:32567;
    server 192.168.1.194:32567;
    server 192.168.1.198:32567;
}
systemctl restart nginx

重启后就可用反向代理来登录kuboard了
http://192.168.1.195:32567


三、部署harbor的两种方式:

官方下载地址:https://github.com/goharbor/harbor/releases
(1)通过kubernetes部署harbor私有库
1、解压harbor_offline_v1.10.5_v2.0.1.tar

cd /root/
tar  -xf  harbor_offline_v1.10.5_v2.0.1.tar

2、安装helm3

cd  /harbor_offline_v1.10.5_v2.0.1/helm
tar -xf  helm-v3.2.4-linux-amd64.tar.gz
cp linux-amd64/helm /usr/local/bin/
chmod +x /usr/local/bin/helm

3、部署storageclass

cd  /root/harbor_offline_v1.10.5_v2.0.1/localpathstorage/
docker load -i local-path-provisioner.tar
docker load -i busybox.tar
kubectl get node --show-labels
vim local-path-storage.yaml
spec:
  template:
    spec:                                #找到此行,添加下面两行内容
      nodeSelector:				#添加
        kubernetes.io/hostname: vm198 	#添加部署到的主机名上
kubectl apply -f local-path-storage.yaml   # 可以通过nodeSelector调整调度策略,另外还需要busybox
kubectl get sc  # 验证
kubectl get pods -n local-path-storage		# 验证

4、加载harbor镜像

cd /root/harbor_offline_v1.10.5_v2.0.1
tar -xf harbor-offline-installer-v1.10.5.tgz
docker load -i harbor/harbor.v1.10.5.tar.gz

5、安装harbor

cd  /root/harbor_offline_v1.10.5_v2.0.1/charts/1.0/
kubectl get svc -A | grep 30002 # 查看30002端口是否被占用
vim  values.yaml
externalURL: http://本机IP:30002         #这里是实际私有仓库访问的地址
storageClass: "local-path"
nodeSelector:         #找到此行,添加下面内容
  kubernetes.io/hostname: vm198	     #新添加此行,后面配置主机名,需要添加多个
kubectl create ns registry     #创建一个名称空间
helm install harbor -f values.yaml -n registry .     #以yaml文件来配置harbor

6、验证

helm list -n registry	#验证  deployed
kubectl get pods -n registry -w	#验证 running
docker login ip:30002 --username admin --password Harbor12345	#登陆验证   
vim /etc/systemd/system/docker.service.d/docker-options.conf  添加 --insecure-registry=本机IP:30002  \		# 所有节点都要添加。
systemctl daemon-reload
systemctl restart docker	#重启后等几分钟k8恢复正常

默认登录账号密码:
admin
Harbor12345
Kubernetes1.18.5部署,kuboard可视化管理界面,harbor私有仓库的部署,docker与dockerfile创建私有镜像_第2张图片
(2)通过docker来部署harbor(与上面方式任选其一即可)
https://github.com/goharbor/harbor/releases

cd  /root
tar  -xf  harbor-offline-installer-v2.2.1-rc1.tgz
mv  harbor  /usr/local/
cd /usr/local/harbor
mv harbor.yml.tmpl  harbor.yml
vim harbor.yml
hostname: 192.168.1.199      #填写本地主机ip内网或者外网都可以,如果需要用域名访问,这里就写域名,比如(api.baidu.com)

# http related config
http:
  # port for http, default is 80. If https enabled, this port will redirect to https port
  port: 80   #注意端口是否被占用

# https related config
#https:          注释以下几行,如果有域名证书可以配置
  # https port for harbor, default is 443   
#  port: 443    #注意端口是否被占用
  # The path of cert and key files for nginx
#  certificate: /your/certificate/path.pem           #如果是阿里云的ssl证书,这里下载域名对应的nginx证书的pem文件位置
#  private_key: /your/private/key/path.key      #这里下载域名对应的nginx证书的key文件位置

harbor_admin_password: Harbor12345    #默认登录admin用户的密码

data_volume: /usr/local/harbor/data      #配置数据映射目录
cat  /etc/docker/daemon.json      #如果未配置443可以不创建此文件,
{
"registry-mirrors": ["http://f1361db2.m.daocloud.io"],    #原有的地址不修改,否则从默认地址拉取镜像会报错
"insecure-registries":["192.168.1.199"]      #添加私库地址
}
启动:
./install.sh
关闭:
cd 到harbor目录下执行:
docker-compose stop

验证:

http://192.168.1.199
admin
Harbor12345

Kubernetes1.18.5部署,kuboard可视化管理界面,harbor私有仓库的部署,docker与dockerfile创建私有镜像_第3张图片
7、进入kuboard页面后,集群里的资源没有显示的情况!

#metrics-server一直是pending状态,这是traints阻止了在master节点上调度新的pod
kubectl get pods -n kube-system
kubectl describe deployment metrics-server -n kube-system

执行下面命令:vm193为是master的hostname,可以设置多次

kubectl taint node vm193 node-role.kubernetes.io/master-
#再次执行后就可以看到metrics-server为running了
kubectl get pods -n kube-system

Kubernetes1.18.5部署,kuboard可视化管理界面,harbor私有仓库的部署,docker与dockerfile创建私有镜像_第4张图片

至此kubernetes集群、kubeoard可视化界面、harbor私库部署完成,下面为扩展的内容。


四、docker与dockerfile做项目镜像部署

1、通过docker做私有镜像的基本环境:
(1)安装docker(如果已经安装可以忽略)

yum -y install docker-ce    #通过yum来安装docker
vim  /etc/docker/daemon.json
{
"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
"insecure-registries": ["192.168.1.198:30002"]
}   #大括号里添加harbor私库的地址

(2)创建一个容器,配置环境

docker pull centos:7.9.2009     #下载一个centos7.9的基本镜像
docker run -itd centos:7.9.2009 bash    #创建一个容器
docker  exec -it   容器id  bash    #进入容器

容器内部署:

mkdir  /opt/pub      #创建一个pub目录,准备存放项目
yum -y install wget   
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo     #在容器里下载yum的扩展包源
yum  clean all
yum  -y install vim  net-tools  epel-release  bash-completion  python-pip   #安装一些基本工具
pip install --upgrade pip    #升级pip的版本,因为这里需要部署一个django的项目,所以需要依赖python,基本项目更根需要来部署
exit

(3)把容器制作成镜像

docker commit  容器id  adminprean:v1.10.1    #做成名为adminprean,版本号为v1.10.1的镜像
docker images     #查看做好的镜像

(4)编写dockerfile文件

备注:构建文件默认名称:Dockerfile
FROM				基于哪个镜像构建新镜像
MAINTAINER(弃用)	镜像维护者信息
LABEL				同上,但用法更加灵活
RUN					构建镜像时运行的Shell命令
COPY				拷贝文件或目录到镜像中
CMD				    运行容器时执行,如果有多个CMD指令,最后一个生效
ENTRYPOINT			运行容器时执行,如果有多个CMD指令,最后一个生效。可单独使用,也可与CMD配合使用
USER				为RUN、CMD、ENTRYPOINT执行指令指定运行用户
EXPOSE				声明容器运行的服务端口
WORKDIR			    为RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录
VOLUME				指定挂载点,使容器中的一个目录具有持久化存储数据的功能
ENV					设置环境变量

参考:
https://www.cnblogs.com/douyi/p/11573783.html
mkdir /root/dockerfile
cd /root/dockerfile
vim  dockerfile     #创建一个dockerfile文件,内容如下
FROM adminprean:v1.10.1     
MAINTAINER adminuser
ADD  adminprean.tar /opt/pub/
RUN locale
RUN localedef -i zh_CN -c -f UTF-8 zh_CN.UTF-8
RUN echo "export LC_ALL=zh_CN.UTF-8" >> /etc/profile && source /etc/profile
ENV LANG zh_CN.UTF-8
ENV LC_CTYPE zh_CN.UTF-8
CMD python3 /opt/pub/adminprean/manage.py runserver 0.0.0.0:8000   #此为djangopython的启动方式,所有网段都可以访问,占用8000端口
EXPOSE 8000

(5)上传项目到/root/dockerfile里(通过xftp来上传即可,这里项目不我公开源码,只是做上传部署介绍,可找其他开源的python项目替换)

cd  /root/dockerfile       #上传的项目文件夹和dockerfile文件放到同一目录下即可
tar  -zcvf  adminprean.tar  /root/dockerfile/adminprean  #注意需要在centos里打包,如果是在windows里压缩再上传到centos里会有编码差异,docker run时会报错
docker build -t adminprean:v1.10.2 /root/dockerfile/      #按照dockerfile写好的内容来创建新的adminprean:v1.10.2,此镜像就可以上传到harbor里了,kubernetes创建时可调用此镜像

(6)测试镜像是否可用

docker  run  -itd  --name=admin adminprean:v1.10.2  bash
docker exec -it  admin bash
ls /opt/pub       #查看容器里是否拷贝了adminprean的项目文件夹
netstat -tunlp | grep 8000   #查看项目是否运行中
locale       #查看当前容器的编码类型
locale -a   #查看当前容器支持的所有编码类型

排错1:项目运行会报以下错误,是容器编码问题:

'ascii' codec can't encode characters in position 20-40: ordinal not in range(128)

centos7.9基础容器编码里没zh_CN.UTF-8时,执行locale命令会出现下面内容:

LANG=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

解决方法:

#在dockerfile文件里添加以下内容
RUN locale
RUN localedef -i zh_CN -c -f UTF-8 zh_CN.UTF-8
RUN echo "export LC_ALL=zh_CN.UTF-8" >> /etc/profile && source /etc/profile
ENV LANG zh_CN.UTF-8
ENV LC_CTYPE zh_CN.UTF-8

(7)上传新镜像到harbor里

docker login 192.168.1.198:30002      #这里的ip可以是域名地址
输入harbor的账号密码:
user
Py123456
docker tag adminprean:v1.10.2 192.168.1.198:30002/adminprean/adminprean:v1.10.2   #给镜像打标记
docker push 192.168.1.198:30002/adminprean/adminprean:v1.10.2  #上传新的镜像到私有仓库里

排错2:如果在docker login后报以下错误:

Error response from daemon: Get https://192.168.1.198:30002/v2/: dial tcp 192.168.1.199:443: connect: connection refused

在vm198里执行:

vim /etc/docker/daemon.json
{ 
"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
"insecure-registries": ["192.168.1.198:30002"]  #添加指定私库的地址,如果用的是80端口可以不跟端口号,如果是其他端口号就需要跟
}
docker daemon-reload
systemc  restart	docker

#注意:如果harbor是用docker部署的,重启docker后,需要手动重启harbor的所有容器,如果是创建到k8s里的,k8s会自动重启harbor,可忽略此注意
docker   ps -a   | grep  goharbor      #查看所有harbor的容器 

(8)编辑yaml文件:
在kubernetesmaster上

注释:不是本项目实例的,只是为解释各个字段的含义,不用创建
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

需要创建两个yaml文件,deplyment用于配置pod,service用于暴露端口

mkdir /root/adminprean-project-kube-yaml
cd /root/adminprean-project-kube-yaml
kubectl create ns adminprean      #创建一个k8s名称空间,需要提前安装好kubernetes集群,和harbor私库
vim delploymen-adminprean.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: adminprean
  namespace: adminprean
  labels:
    app: adminprean
spec:
  replicas: 2
  selector:
    matchLabels:
      app: adminprean
  strategy:
    rollingUpdate:  ##滚动更新策略
      maxSurge: 2
      maxUnavailable: 2
  template:
    metadata:
      labels:
        app: adminprean
    spec:
      containers:
        - name: adminprean
          image: 192.168.1.198:30002/adminprean/adminprean:v1.10.2
          ports:
            - name: http
              containerPort: 8000
vim service-adminprean.yaml
apiVersion: v1
kind: Service
metadata: 
  name: adminprean
  labels: 
    app: adminprean
  namespace: adminprean     #在指定名称空间里创建
spec: 
  ports: 
  - port: 8000
    nodePort: 30080       #这里的nodeport需要在30000以上
  selector: 
    app: adminprean
  type: NodePort

(9)创建pod

kubectl  apply -f  deployment-adminprean.yaml
kubectl  apply -f  service-adminprean.yaml
kubectl get pods -n adminprean

(10)验证
通过浏览器在kubernetes任意master节点上登录:
http://192.168.1.198:30080/prean01/studentlogin/

五、jenkins部署与连用

你可能感兴趣的:(kubernetes,docker,harbor,docker,运维,ssh,kubernetes)