一、基于Dockerfile构建nginx镜像
1.1 准备Dockerfile用到的文件
- 修改镜像源为清华大学镜像源,创建sources.list文件
网址:https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/ - 下载nginx安装包
网址:https://nginx.org/en/download.html - 启动nginx容器,从容器中拷贝nginx.conf文件到宿主机
- 编写docker-entrypoint.sh脚本,并添加可执行权限
1.2 编写Dockerfile文件
cat >> Dockerfile <<EOF
# 基于底层镜像
FROM ubuntu:20.04
# label标签是key/value形式 描述镜像信息
LABEL "maintiner"="Chris"
# 修改镜像源信息
COPY sources.list /etc/apt/sources.list
# 更新镜像源 安装编译依赖 创建目录
RUN apt update && apt install -y iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server nfs-common lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev gcc openssh-server iotop unzip zip make vim && mkdir -p /data/nginx
# 拷贝压缩包并自动解压
ADD nginx-1.20.2.tar.gz /usr/local/src
# 编译并删除解压目录
RUN cd /usr/local/src/nginx-1.20.2 && ./configure --prefix=/apps/nginx && make && make install && ln -sv /app/nginx/sbin/nginx /usr/bin && rm -rf /usr/local/src/nginx-1.20.2
# 拷贝nginx.conf配置文件
ADD nginx.conf /apps/nginx/conf/nginx.conf
# 拷贝docker-entrypoint.sh
ADD docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
# 链接标准输出和错误日志 可docker logs查看
RUN ln -sv /dev/stdout /apps/nginx/logs/access.log
RUN ln -sv /dev/stderr /apps/nginx/logs/error.log
# 添加nginx用户和组 修改目录归属用户和组
RUN groupadd -g 2022 nginx && useradd -g nginx -s /usr/sbin/nologin -u 2022 nginx && chown -R nginx.nginx /apps/nginx /data/nginx
# 容器占用端口
EXPOSE 80 443
# 启动命令
#CMD ["/apps/nginx/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["-g","daemon off;"]
EOF
1.3 构建镜像
docker build -t 192.168.204.200/n60/nginx:v1.20.2 .
1.4 运行容器
docker run -itd -p80:80 192.168.204.200/n60/nginx:v1.20.2
1.5 访问容器
二、Docker的cpu和内存的资源限制
2.1 下载压测镜像
docker pull lorel/docker-stress-ng:latest
2.2 压测cpu
- 容器需要使用cpu个数为2
docker run -it --rm lorel/docker-stress-ng --cpu 2
top 按1查看
-
docker stats查看 限制容器使用cpu个数为1,容器需要使用的cpu个数为2
docker run -it --cpus 1 --rm lorel/docker-stress-ng --cpu 2
top 按1查看
-
docker stats - 在宿主机上查看分配给容器的cpu
cat /sys/fs/cgroup/cpu,cpuacct/docker/fd984ff398613870ba22adb329415fd4ea214d97e1f24d52b2cf6862085e16b2/cpu.cfs_quota_us
文件中的单位是毫核,除以1000是百分比的形式,再除以100是cpu个数
2.3 压测内存
- 默认两个vm,占用两个cpu,使用命令限制容器使用一个cpu
docker run -it --cpus 1 --rm lorel/docker-stress-ng --vm 2
- 容器需要使用两个vm,一个vm使用256M
docker stats - 限制容器使用内存200M
docker run -it --cpus 1 -m 200m --rm lorel/docker-stress-ng --vm 2
docker stats
- 在宿主机上查看分配给容器的mem
cat /sys/fs/cgroup/memory/docker/e2dd9d29676f664507e233366b6de911f50bacd626033bf362543a57c6cd866c/memory.limit_in_bytes
文件中单位是字节,除以1024是K,再除以1024是M
三、Docker存储卷和网络
3.1 查看容器详细信息
docker inspect 容器id
- Lower Dir:image镜像层(镜像本身,只读)
- Upper Dir:容器的上层(读写)
- Merged Dir:容器的文件系统,使用Union FS(联合文件系统)将lower dir和upper dir合并给容器使用
- Work Dir:容器在宿主机的工作目录
3.2 容器在宿主机的目录
- docker数据默认在宿主机/var/lib/docker目录下,在容器中写入的文件,一旦容器被删除,目录丢失
3.3 容器挂载目录
- 创建目录
mkdir -p /data/testapp
echo "testapp page" > /data/testapp/index.html
- 启动两个tomcat容器
docker run -tid --name web1 -v /data/testapp:/usr/local/tomcat/webapps/testapp -p 8080:8080 tomcat:8.5.73
docker run -tid --name web2 -v /data/testapp:/usr/local/tomcat/webapps/testapp -p 8081:8080 tomcat:8.5.73
- 两个容器访问的数据目录一样
web1
web2
- 挂载只读目录
docker run -itd --name web3 -v /data/tomcat/conf/server.xml:/usr/local/tomcat/conf/server.xml:ro -v /data/testapp:/usr/local/tomcat/webapps/testapp -p 8083:8080 tomcat:8.5.73
server.xml只读
- 创建docker volume
docker volume create n60
创建卷n60
- 挂载docker volume
docker run -it -p 3306:3306 -v n60:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.6.38
3.4 Docker网络介绍
- 查看docker网络
docker network ls
四、k8s各组件的功能介绍
4.1 kube-apiserver
- 运行在master节点上
- Kubernetes API server提供k8s各类资源对象的增删改查及watch等HTTP Rest接口,这些对象包括pods、services、replicationcontrollers等,API Server为REST等操作提供服务,并为集群的共享状态提供前端,所有其他组件都通过改前端进行交互。
- 端口默认值为6443,可通过启动参数"--secure-port"的值来修改默认值。
- 默认IP地址为非本地(Non-Localhost)网络端口,通过启动参数"--bind-address"设置改值。
- 端口用于接收客户端、dashboard等外部HTTPS请求。
- 用于基于Tocken文件或客户端证书以及HTTP Base的请求。
- 用于基于策略的授权。
4.2 kube-scheduler
- 运行在master节点上
- Kubernetes调度器是一个控制面进程,负责Pods指派到节点上。
- 通过调度算法为待调度Pod列表的每个Pod从可用Node列表中选择一个最合适的Node,并将信息写入etcd中。
- node节点上的kubelet通过API Server监听到kubernetes scheduler产生的Pod绑定信息,然后获取对应的Pod清单,下载Image,并启动容器。
- 策略:
LeastRequestedPriority:优先从备选节点列表中选择资源消耗最小的节点(CPU+内存)。
CalculateNodeLabelPriority:优先选择含有指定Label的节点。
BalancedResourceAllocation:优先从备选节点列表中选择各项资源使用率最均衡的节点。
4.3 kube-controller-manager
- 运行在master节点上
- Controller Manager还包括一些子控制器(副本控制器、节点控制器、命名空间控制器和服务账号控制器等),控制器作为集群内部的管理控制中心,负责集群内的Node、Pod副本、服务端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的管理,当某个Node意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群中的pod副本始终处于预期的工作状态。
- 每间隔5秒检查一次节点的状态。
- 如果没有收到节点的心跳,则将该node节点标记为不可达。
- 在标记为无法访问之前等待40秒。
- 如果该node节点被标记为无法访问后5分钟还没有恢复,Controller manager会删除当前node节点的所有pod并在其它可用节点重建这些pod。
- pod高可用机制:
node monitor period:节点监视周期,5s
node monitor grace period:节点监视器宽限期,40s
pod eviction timeout:pod驱逐超时时间,5m
4.4 kube-proxy
- 运行在node节点上
- 反映了node上Kubernetes API中定义的服务,并可以通过一组后端进行简单的TCP、UDP和SCTP流转发或者在一组后端进行循环TCP、UDP和SCTP转发,用户必须使用apiserver API创建一个服务来配置代理,其实就是kube-proxy通过在主机上维护网络规则并执行连接转发来实现Kubernetes服务访问。
- 监听API Server中服务对象的变化,再通过管理IPtables或者IPVS规则,实现网络的转发。
- 不同版本可支持三种工作模式:
UserSpace:k8s v1.1之前使用,k8s 1.2及以后就已经淘汰。
IPtables:k8s 1.1版本开始支持,1.2开始为默认模式
IPVS:k8s 1.9引入到1.11为正式版本,需要安装ipvsadm、ipset工具包和加载ip_vs内核模块 - 当kube-proxy以IPVS代理模式启动时,kube-proxy将验证节点上是否安装了IPVS模块,如果未安装,则kube-proxy将回退到IPtables代理模式。
- 使用IPVS模式,kube-proxy会监视Kubernetes Service对象和Endpoints,调用宿主机内核Netlink接口以相应的创建IPVS规则并定期与Kubernetes Service对象Endpoints对象同步IPVS规则,以确保IPVS状态与期望一直,访问服务时,流量将被重定向到其中一个后端Pod,IPVS使用哈希表作为底层数据结构并在内核空间中工作,这意味着IPVS可以更快地重定向流量,并且在同步代理规则时具有更好的性能。
4.5 kubelet
- 运行在node节点上
- worker节点的代理组件,监视分配给节点的pod
- 向master汇报node节点的状态信息
- 接收指令并在Pod中创建docker容器
- 准备Pod所需的数据卷
- 返回Pod的运行状态
- 在node节点执行容器健康检查
4.6 kubectl
- 是一个通过命令对kubernetes集群进行管理的客户端工具。
4.7 etcd
- 是由CoreOS公司开发,目前是kubernetes默认使用的key-value数据存储系统,用于保存kubernetes的所有集群数据,etcd支持分布式集群功能,生产环境使用时需要为etcd数据提供定期备份机制。
4.8 dns
- DNS负责为整个集群提供DNS服务,从而实现服务之间的访问。
4.9 Dashboard
- Dashboard是基于网页的kubernetes用户界面,可以使用Dashboard获取运行在集群中的应用的概览信息,也可以创建或者修改kubernetes资源(如Deployment、Job、DaemonSet等),也可以对Deployment实现弹性伸缩、发起滚动升级、重启Pod或者使用向导创建新的应用。
五、部署高可用k8s集群
主机环境准备
IP | 角色 | 系统 | 内存 | CPU |
---|---|---|---|---|
192.168.96.11 | k8s-master1 | ubutu 20.04.3 | 2G | 2C |
192.168.96.12 | k8s-master2 | ubutu 20.04.3 | 2G | 2C |
192.168.96.13 | k8s-node1 | ubutu 20.04.3 | 2G | 2C |
192.168.96.14 | k8s-node2 | ubutu 20.04.3 | 2G | 2C |
192.168.96.12 | k8s-etcd1 | ubutu 20.04.3 | 2G | 2C |
192.168.96.13 | k8s-etcd2 | ubutu 20.04.3 | 2G | 2C |
192.168.96.14 | k8s-etcd3 | ubutu 20.04.3 | 2G | 2C |
192.168.96.12 | k8s-harbor1 | ubutu 20.04.3 | 2G | 2C |
192.168.96.13 | k8s-harbor2 | ubutu 20.04.3 | 2G | 2C |
192.168.96.12 | k8s-keepalived1 | ubutu 20.04.3 | 2G | 2C |
192.168.96.13 | k8s-keepalived2 | ubutu 20.04.3 | 2G | 2C |
192.168.96.12 | k8s-haproxy1 | ubutu 20.04.3 | 2G | 2C |
192.168.96.13 | k8s-haproxy2 | ubutu 20.04.3 | 2G | 2C |
5.1 部署keepalived和haproxy
- 192.168.96.12主机配置keepalived
apt install -y keepalived haproxy
cat > /etc/keepalived/keepalive.conf <<EOF
global_defs {
notification_email {
acassen
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface ens33
garp_master_delay 10
smtp_alert
virtual_router_id 60
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.96.188 dev ens33 label ens33:0
192.168.96.189 dev ens33 label ens33:1
192.168.96.190 dev ens33 label ens33:2
192.168.96.191 dev ens33 label ens33:3
}
}
EOF
systemctl restart keepalived.service
ifconfig | grep 192.168. # 查看vip
- 192.168.96.13主机配置keepalived
apt install -y keepalived haproxy
cat > /etc/keepalived/keepalive.conf <<EOF
global_defs {
notification_email {
acassen
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
garp_master_delay 10
smtp_alert
virtual_router_id 60
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.96.188 dev ens33 label ens33:0
192.168.96.189 dev ens33 label ens33:1
192.168.96.190 dev ens33 label ens33:2
192.168.96.191 dev ens33 label ens33:3
}
}
EOF
systemctl restart keepalived.service
- 192.168.96.12主机,验证vip切换,停止keepalived,再启动
ifconfig | grep 192.168. # 查看vip
systemctl stop keepalived.service # 停止keepalived
ifconfig | grep 192.168. # vip飘到备机
systemctl start keepalived.service # 再启动keepalived
ifconfig | grep 192.168. # vip回到主机
- 192.168.96.12主机配置haproxy
cat > /etc/haproxy/haproxy.cfg <<EOF
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen k8s-6443
bind 192.168.96.188:6443
mode tcp
server 192.168.96.11 192.168.96.11:6443 check inter 2s fall 3 rise 5
server 192.168.96.12 192.168.96.12:6443 check inter 2s fall 3 rise 5
EOF
systemctl restart haproxy
ss -ntl # 查看vip端口是否监听
- 192.168.96.13主机配置haproxy
cat > /etc/haproxy/haproxy.cfg <<EOF
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen k8s-6443
bind 192.168.96.188:6443
mode tcp
server 192.168.96.11 192.168.96.11:6443 check inter 2s fall 3 rise 5
server 192.168.96.12 192.168.96.12:6443 check inter 2s fall 3 rise 5
EOF
echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf # 修改内核参数,允许服务监听在本机没有的地址上
sysctl -p # 使参数生效
systemctl restart haproxy
ss -ntl # 查看vip端口是否监听
5.2 部署harbor
- 192.168.96.12安装harbor
cp harbor.yml.tmpl harbor.yml # 赋值harbor配置文件,然后修改hostname为harbor域名
mkdir certs # 创建目录,用作存放证书
openssl genrsa -out ./harbor-ca.key # 生成私有key
openssl req -x509 -new -nodes -key ./harbor-ca.key -subj "/CN=HARBOR_DOMAIN" -days 3650 -out ./harbor-ca.crt # 给harbor的域名签发十年有效期的证书,然后修改harbor中证书和私钥路径
./install.sh --with-trivy --with-chartmuseum # 安装harbor
然后修改电脑hosts文件,用harbor域名从浏览器中访问,新建项目测试