目录
一、概述
1.简介
2.特点
3.Harbor架构组件
4.Harbor误区
二、使用Kubeadm搭建Kubernetes
1.部署思路
2.环境准备
3.所有节点安装Docker
4.所有节点安装Kubeadm、Kubelet和Kubectl
5.部署Kubernetes集群
5.1初始化Kubeadm
5.2设定Kubectl
6.在所有节点部署Flannel
6.1Master节点部署Flannel
6.2Node节点部署Flannel
7.测试pod资源创建
7.1暴露端口提供服务
7.2测试访问
8.扩容
三、部署Dashboard
四、搭建Harbor私有仓库
1.所有Node节点修改Docker配置文件
2.安装Harbor
3.生成证书
4.访问私有仓库
5.测试私有仓库
五、内核参数优化
一、概述
1.简介
Docker容器应用的开发和运行离不开可靠的镜像管理,虽然Docker官方也提供了公共的镜像仓库,但是从安全和效率等方面考虑,部署我们私有环境内的Registry也是非常必要的。Harbor是由VMware公司开源的企业级的Docker Registry管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。
2.特点
- 基于角色控制:用户和仓库都是基于项目进行组织的,而用户在项目中可以拥有不同的权限。
- 基于镜像的复制策略:镜像可以在多个Harbor实例之间进行复制(同步)。
- 支持 LDAP/AD:Harbor 可以集成企业内部已有的 AD/LDAP(类似数据库的一张表),用于对已经存在的用户认证和管理。
- 镜像删除和垃圾回收:镜像可以被删除,也可以回收镜像占用的空间。
- 图形化用户界面:用户可以通过浏览器来浏览,搜索镜像仓库以及对项目进行管理。
- 审计管理:所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。
- 支持 RESTful API:RESTful API 提供给管理员对于 Harbor 更多的操控, 使得与其它管理软件集成变得更容易。
- Harbor和docker registry的关系:Harbor实质上是对docker registry做了封装,扩展了自己的业务模板。
3.Harbor架构组件
- Proxy:反向代理工具,他是一个nginx前端代理,主要是分发前端页面ui访问和镜像上传和下载流量。
- Registry:负责存储docker镜像,处理上传/下载命令。对用户进行访问控制,它指向一个token服务,强制用户的每次docker pull/push请求都要携带一个合法的token,registry会通过公钥对token进行解密验证。
- Core service:Harbor的核心功能:
- UI:图形界面。
- Webhook:及时获取registry上image状态变化情况,在registry上配置 webhook,把状态变化传递给UI模块。
- Token服务:复杂根据用户权限给每个docker push/p/ull命令签发token。Docker客户端向registry服务发起的请求,如果不包含token,会被重定向到这里,获得token后再重新向registry进行请求。
- Database:提供数据库服务,存储用户权限,审计日志,docker image分组信息等数据。
- Log collector:为了帮助监控harbor运行,复责收集其他组件的log,供日后进行分析。
4.Harbor误区
- 误区一: Harbor是负责存储容器镜像的 (Harbor是镜像仓库,那么它就应当是存储镜像的)其实关于镜像的存储,Harbor使用的是官方的docker registry服务去完成,至于registry是用本地存储或者s3都是可以的,Harbor的功能是在此之上提供用户权限管理、镜像复制等功能,提高使用的registry的效率。
- 误区二:Harbor镜像复制是存储直接复制 (镜像的复制,很多人以为应该是镜像分层文件的直接拷贝)其实Harbor镜像复制采用了一个更加通用、高屋建瓴的做法,通过docker registry 的API去拷贝,这不是省事,这种做法屏蔽了繁琐的底层文件操作、不仅可以利用现有docker registry功能不必重复造轮子,而且可以解决冲突和一致性的问题。
二、使用Kubeadm搭建Kubernetes
主机名 | 硬件要求 | 主机IP | 安装服务 |
Master | 2C/4G | 192.168.241.11 | Docker、Kubeadm、Kubelet、Kubectl、Flannel |
Node1 | 2C/2G | 192.168.241.22 | Docker、Kubeadm、Kubelet、Kubectl、Flannel |
Node2 | 2C/2G | 192.168.241.23 | Docker、Kubeadm、Kubelet、Kubectl、Flannel |
Harbor节点(hub.cxk.com) | 2C/2G | 192.168.241.24 | Docker、Docker-Compose、Harbor-offline-v1.2.2 |
1.部署思路
- 在所有节点上安装Docker和kubeadm
- 部署Kubernetes Master
- 部署容器网络插件
- 部署 Kubernetes Node,将节点加入Kubernetes集群中
- 部署 Dashboard Web 页面,可视化查看Kubernetes资源
- 部署 Harbor 私有仓库,存放镜像资源
2.环境准备
所有节点,关闭防火墙规则,关闭selinux,关闭swap交换
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/enforcing/disabled/' /etc/selinux/config
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
swapoff -a
#交换分区必须要关闭
sed -ri 's/.*swap.*/#&/' /etc/fstab
#永久关闭swap分区,&符号在sed命令中代表上次匹配的结果
#加载 ip_vs 模块
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done
#修改主机名
hostnamectl set-hostname master1
hostnamectl set-hostname node1
hostnamectl set-hostname node2
hostnamectl set-hostname hub.cxk.com
#所有节点修改hosts文件
vim /etc/hosts
192.168.241.11 master1
192.168.241.22 node1
192.168.241.23 node2
192.168.241.24 hub.cxk.com
#调整内核参数
cat > /etc/sysctl.d/kubernetes.conf << EOF
#开启网桥模式,可将网桥的流量传递给iptables链
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
#关闭ipv6协议
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF
#生效参数
sysctl --system
3.所有节点安装Docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
}
}
EOF
#使用Systemd管理的Cgroup来进行资源控制与管理,因为相对Cgroupfs而言,Systemd限制CPU、内存等资源更加简单和成熟稳定。
#日志使用json-file格式类型存储,大小为100M,保存在/var/log/containers目录下,方便ELK等日志系统收集和管理日志。
systemctl daemon-reload
systemctl restart docker.service
systemctl enable docker.service
docker info | grep "Cgroup Driver"
Cgroup Driver: systemd
4.所有节点安装Kubeadm、Kubelet和Kubectl
#定义kubernetes源
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubelet-1.20.11 kubeadm-1.20.11 kubectl-1.20.11
#开机自启kubelet
systemctl enable kubelet.service
#K8S通过kubeadm安装出来以后都是以Pod方式存在,即底层是以容器方式运行,所以kubelet必须设置开机自启
5.部署Kubernetes集群
#查看初始化需要的镜像
kubeadm config images list
#在 master 节点上传 v1.20.11.zip 压缩包至 /opt 目录
unzip v1.20.11.zip -d /opt/k8s
cd /opt/k8s/v1.20.11
for i in $(ls *.tar); do docker load -i $i; done
复制镜像和脚本到 node 节点,并在 node 节点上执行脚本加载镜像文件
scp -r /opt/k8s root@node1:/opt
scp -r /opt/k8s root@node2:/opt
cd /opt/k8s/v1.20.11/
for i in $(ls *.tar); do docker load -i $i; done
5.1初始化Kubeadm
#初始化kubeadm 在Master操作
kubeadm config print init-defaults > /opt/kubeadm-config.yaml
cd /opt/
vim kubeadm-config.yaml
......
11 localAPIEndpoint:
12 advertiseAddress: 192.168.241.11 #指定master节点的IP地址
13 bindPort: 6443
......
34 kubernetesVersion: v1.20.11 #指定kubernetes版本号 此处需要修改
35 networking:
36 dnsDomain: cluster.local
37 podSubnet: "10.244.0.0/16" #指定pod网段,10.244.0.0/16用于匹配flannel默认网段,此处需要添加
38 serviceSubnet: 10.96.0.0/16 #指定service网段
39 scheduler: {}
#末尾再添加以下内容
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs #把默认的kube-proxy调度方式改为ipvs模式
kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log
#--experimental-upload-certs 参数可以在后续执行加入节点时自动分发证书文件,K8S V1.16版本开始替换为 --upload-certs
#tee kubeadm-init.log 用以输出日志
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
-17行-- --bind-address=192.168.241.11
-26行-# - --port=0
-37行-host: 192.168.241.11
-51行-host: 192.168.241.11
kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
这里如果报错NotHealthy,可以把 /etc/kubernetes/manifests/kube-controller-manager.yaml和/etc/kubernetes/manifests/kube-scheduler.yaml
--bind-address=127.0.0.1 变动为--bind-address=192.168.241.11
#修改成k8s的控制节点master1的ip
把httpGet:字段下的hosts由127.0.0.1变成192.168.241.11(有两处)
#- --port=0 # 搜索port=0,把这一行注释掉
kubectl get cs
#如果是该报错The connection to the server localhost:8080 was refused - did you specify the right host or port?
出现这个问题的原因是kubectl命令需要使用kubernetes-admin来运行,解决方法如下,将主节点中的【/etc/kubernetes/admin.conf】文件拷贝到从节点相同目录下,然后配置环境变量
执行下面两条命令
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile
systemctl restart kubelet
5.2设定Kubectl
kubectl需经由API server认证及授权后方能执行相应的管理操作,kubeadm 部署的集群为其生成了一个具有管理员权限的认证配置文件 /etc/kubernetes/admin.conf,它可由 kubectl 通过默认的 “$HOME/.kube/config” 的路径进行加载。
mkdir -p $HOME/.kube
#$HOME表示为当前用户的家目录
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
#复制kubernetes目录下的admin.conf文件到$HOME/.kube/目录下,命名为config
chown $(id -u):$(id -g) $HOME/.kube/config
#修该文件的属组与属组
6.在所有节点部署Flannel
#所有节点上传flannel镜像 flannel.tar 到 /opt 目录
cd /opt
unzip kuadmin.zip
docker load -i flannel-cni-v1.2.0.tar
docker load -i flannel-v0.22.2.tar
6.1Master节点部署Flannel
kubectl apply -f kube-flannel.yml
kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready control-plane,master 27m v1.20.11
6.2Node节点部署Flannel
#在node1和node2分别输入以下命令
kubeadm join 192.168.241.11:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:94b1c4ea077ad4e9ea86b5238c714750ecd6652cae7d48a658696353f708ea55
#此命令在kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log命令执行完的末尾
也可以使用cat kubeadm-init.log查看token的密钥,使得node1加入到群集中
#在Master节点查看
kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready control-plane,master 17m v1.20.11
node1 Ready <none> 2m28s v1.20.11
node2 Ready <none> 25s v1.20.11
kubectl get pod -n kube-flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-8k8zh 1/1 Running 0 3m39s
kube-flannel-ds-jt4t9 1/1 Running 0 96s
kube-flannel-ds-sb77l 1/1 Running 0 4m46s
kubectl get pod -n kube-flannel -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel-ds-8k8zh 1/1 Running 0 3m50s 192.168.241.22 node1 <none> <none>
kube-flannel-ds-jt4t9 1/1 Running 0 107s 192.168.241.23 node2 <none> <none>
kube-flannel-ds-sb77l 1/1 Running 0 4m57s 192.168.241.11 master1 <none> <none>
7.测试pod资源创建
#在Master节点操作
kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6799fc88d8-nwdmz 1/1 Running 0 90s 10.244.2.2 node2 <none> <none>
curl 10.244.2.2
7.1暴露端口提供服务
#在Master节点操作
kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23m
nginx NodePort 10.101.241.60 <none> 80:30904/TCP 15s
7.2测试访问
8.扩容
kubectl scale deployment nginx --replicas=3
#--replicas保证有3台机器
Kubectl get pods
三、部署Dashboard
#在Master节点操作
上传 recommended.yaml 文件到 /opt/k8s 目录中
cd /opt/k8s
vim recommended.yaml
#默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部
kubectl apply -f recommended.yaml
#创建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
https://NodeIP:30001
四、搭建Harbor私有仓库
因为主机映射、主机名和Docker都已安装,我们就不做重复操作了
1.所有Node节点修改Docker配置文件
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
#此处可能镜像加速器有问题
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"insecure-registries": ["https://hub.cxk.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
2.安装Harbor
#上传 harbor-offline-installer-v1.2.2.tgz 和 docker-compose 文件到 /opt 目录
cd /opt
cp docker-compose /usr/local/bin/
chmod +x /usr/local/bin/docker-compose
tar zxvf harbor-offline-installer-v1.2.2.tgz
cd harbor/
vim harbor.cfg
5 hostname = hub.cxk.com
9 ui_url_protocol = https
24 ssl_cert = /data/cert/server.crt
25 ssl_cert_key = /data/cert/server.key
59 harbor_admin_password = Harbor12345
3.生成证书
#生成证书
mkdir -p /data/cert
cd /data/cert
#生成私钥
openssl genrsa -des3 -out server.key 2048
输入两遍密码:123123
#生成证书签名请求文件
openssl req -new -key server.key -out server.csr
输入私钥密码:123123
Country Name (2 letter code) [XX]:输入国家名:CN
State or Province Name (full name) []输入省名:SX
Locality Name (eg, city) [Default City]输入市名:YQ
Organization Name (eg, company) [Default Company Ltd]输入组织名:cxk
Organizational Unit Name (eg, section) []输入机构名:cxk
Common Name (eg, your name or your server's hostname) []输入域名:hub.cxk.com
输入管理员邮箱:admin@cxk.com
其它全部直接回车
#备份私钥
cp server.key{,_bak}
#清除私钥密码
openssl rsa -in server.key_bak -out server.key
#签名证书
openssl x509 -req -days 1000 -in server.csr -signkey server.key -out server.crt
chmod +x /data/cert/*
cd /opt/harbor/
./install.sh
4.访问私有仓库
在本地使用火狐浏览器访问:https://hub.cxk.com
添加例外 -> 确认安全例外
用户名:admin
密码:Harbor12345
5.测试私有仓库
#在一个node节点上登录harbor
docker login -u admin -p Harbor12345 https://hub.cxk.com
#上传镜像
docker tag nginx:latest hub.cxk.com/library/nginx:v1
docker push hub.cxk.com/library/nginx:v1
#在master节点上删除之前创建的nginx资源
kubectl delete deployment nginx
#在Master节点操作
kubectl create deployment nginx-deployment --image=hub.cxk.com/library/nginx:v1 --port=80 --replicas=3
deployment.apps/nginx-deployment created
kubectl expose deployment nginx-deployment --port=30000 --target-port=80
service/nginx-deployment exposed
kubectl get svc,pods
yum install ipvsadm -y
ipvsadm -Ln
curl 10.109.243.43:30000
kubectl edit svc nginx-deployment
#在26行 type: NodePort
#把调度策略改成NodePort可以支持对外访问
service/nginx-deployment edited
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7h53m
nginx NodePort 10.108.250.11 <none> 80:32319/TCP 24m
nginx-deployment NodePort 10.109.243.43 <none> 30000:31011/TCP 5m3s
#将cluster-admin角色权限授予用户system:anonymous
kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
五、内核参数优化
cat > /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1 #启用网络桥接接口
net.bridge.bridge-nf-call-ip6tables=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
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963 #指定最大文件句柄数
fs.nr_open=52706963 #仅4.4以上版本支持
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF