DevOps CI/CD、ceph、K8S/istio流量治理

目录

  • 一、前述
    • 1.1 基本架构
    • 1.2 本文测试环境
    • 1.3 部署次序
  • 二、基础支撑层
    • 2.1 os-w服务
    • 2.2 管理节点
    • 2.3 DNS服务配置
    • 2.4 CA证书配置
      • 2.4.1 cfssl工具安装
      • 2.4.2 证书产生过程
    • 2.5 DHCP服务
    • 2.6 web下载服务
  • 三、CI/CD层
    • 3.1 镜像仓库harbor
      • 3.1.1 安装前准备
      • 3.1.2 安装harbor
      • 3.1.3 访问测试
      • 3.1.4 镜像push和pull测试
    • 3.2 代码仓库Gitlab
      • 3.2.1 安装及配置gitlab
      • 3.2.1 测试
        • 3.2.1.1 ssh方式
        • 3.2.1.2 http/https方式
    • 3.3 配置Gitlab CI/CD、Gitlab Runner
      • 3.3.1 安装 Gitlab Runner
      • 3.3.2 注册runner executor/docker-in-docker
      • 3.3.3 编写.gitlab-ci.yml
      • 3.3.4 CI/CD测试
        • 3.3.4.1 配置变量及webhok token
        • 3.3.4.2 push测试
        • 3.3.4.3 webhook测试
  • 四、存储层/ceph分布式存储
    • 4.1 基本配置
      • 4.1.1 所有节点基本配置
      • 4.1.2 管理节点
      • 4.1.3 ceph集群节点
    • 4.2 管理机点配置
      • 4.2.1 ceph集群全局唯一性标识配置
      • 4.2.2 keyring配置
      • 4.2.3 ceph.conf初始配置
      • 4.2.4 客户端ceph命令配置
    • 4.3 mon进程配置
      • 4.3.1 ceph.mon.keyring
      • 4.3.2 monitor map配置
      • 4.3.3 创建monitor数据目录
      • 4.3.4 启动monitor服务
    • 4.4 mgr进程配置
      • 4.4.1 配置mgr服务
      • 4.4.2 配置mgr模块
      • 4.4.2 配置mgr模块dashbord
    • 4.5 存储osd配置
      • 4.5.1 ceph.conf配置
      • 4.5.2 添加ceph卷
    • 4.6 mds进程配置
      • 4.6.1 配置mds服务
      • 4.6.2 创建fs卷
      • 4.6.3 cephfs mount测试
    • 4.7 rbd块存储配置
      • 4.7.1 创建块设备
      • 4.7.2 用户使用块设备
    • 4.8 rgw配置
      • 4.8.1 存储池配置
      • 4.8.2 rgw进程配置
        • 4.8.2.1 keyring配置
        • 4.8.2.2 rgw服务配置
      • 4.8.3 rgw测试
  • 五、计算层/k8s/istio
    • 5.1 K8S节点配置
      • 5.1.1 基础配置
        • 5.1.1.1 基础包和内核参数
        • 5.1.1.2 容器运行时配置
        • 5.1.1.3 kubectl kubelet kubeadm安装
        • 5.1.1.4 k8s系统镜像准备
      • 5.1.2 master节点配置
      • 5.1.3 worker节点配置
      • 5.1.4 管理机mgm配置kubectl
      • 5.1.5 访问私有仓库harbor配置
        • 5.1.5.1 k8s/crictl访问私有仓库配置
        • 5.1.5.2 测试
        • 5.1.5.3 secrets存储私仓帐号
    • 5.2 网络配置calico
      • 5.2.1 Calico安装
      • 5.2.2 Calicoctl工具
    • 5.3 metrics-server配置
    • 5.4 metallb配置
      • 5.4.1 安装
      • 5.4.2 配置LB网络
      • 5.4.3 测试
    • 5.5 Ingress配置
      • 5.5.1 Ingress Controller
      • 5.5.2 nginx ingress
        • 5.5.2.1 安装
        • 5.5.2.2 测试
      • 5.5.3 istio ingress
        • 5.5.3.1 安装istio(从私仓安装)
        • 5.5.3.2 边车代理注入
        • 5.5.3.3 http测试
        • 5.5.3.4 https测试
        • 5.5.3.5 istio dashboard
    • 5.6 存储持久化
      • 5.6.1 准备
      • 5.6.2 ceph-fs csi配置
        • 5.6.2.1 安装ceph-fs csi
        • 5.6.2.2 sc存储类配置
        • 5.6.2.3 无状态部署测试
        • 5.6.2.4 有状态部署测试
      • 5.6.3 ceph-rbd csi配置
        • 5.6.3.1 安装ceph-rbd csi
        • 5.6.3.2 sc存储类配置
        • 5.6.3.3 无状态部署测试
        • 5.6.3.4 有状态部署测试
    • 5.7 测试
      • 5.7.1 istio流量治理
        • 5.7.1.1 微服务准备
        • 5.7.1.2 百分比流量策略发布
        • 5.7.1.3 识别浏览器类型
        • 5.7.1.4 识别header信息
      • 5.7.2 CI/CD测试(AB部署)
        • 5.7.2.1 Ingress配置http/https
        • 5.7.2.2 制作gitlab-ci
        • 5.7.2.3 开发人员push发布到测试环境
        • 5.7.2.4 OA流程调用webhook发布到正式环境
      • 5.7.3 滚动更新
      • 5.7.4 HPA弹性计算
  • 六、第三方镜像部署
    • 6.1 数据库mysql配置(有状态部署)
    • 6.2 私有化部署chatgpt
  • 七、运维层
    • 7.1 dashboard配置
    • 7.2 rancher
      • 7.2.1 rancher节点安装
        • 7.2.1.1 rancher-web被访问时的证书配置
        • 7.2.1.2 私仓配置
        • 7.2.1.3 安装rancher节点
        • 7.2.1.4 访问rancher web
      • 7.2.2 添加外部k8s集群
      • 7.2.3 新增k8s集群
    • 7.3 prometheus/grafana
      • 7.3.1 kube-prometheus安装
      • 7.3.2 应用配置样例
        • 7.3.2.1 ceph Metrics(集群外部ceph)
        • 7.3.2.2 istio边车容器metrics(自动发现)
        • 7.3.2.3 nginx ingress Metrics
        • 7.3.2.4 mysql Metrics
      • 7.3.3 配置rule和告警
      • 7.3.3.1 配置rule
      • 7.3.3.1 配置alert
  • 八、附录

一、前述

涉及到多个开源软件,知识点较多。
由于篇幅有限,针对每一个知识点,讲述了其基本操作,对于某单一开源软件,若需更详细配置说明,可点赞收藏,并留言,大家一起探讨。

如果本文有错误的地方,欢迎指出!

类似架构在工作中曾配置很多次,每一次配置都能学习到新知识点,知识需持续更新。

在实际工作中,有较多镜像从需Internet下载,建议先pull镜像,转存私仓。

1.1 基本架构

在实际工作中,有较多项目的需求中重要诉求是为开发人员创建敏捷开发环境、或对企业进行类似敏捷开发培训。

通过合理的架构设计,可以让开发和运维各自更专注自己职责业务工作和业务功能实现,同时又能高效配合,共同保证整个系统运营性的高性能、高可用。构架搭建后,软件项目从开发到交付,全流程自动化。

基本架构如下图所示。

在这里插入图片描述

本文基于开源软件建立demo环境。

项目简述
开发层开发人员组成,c++/java/go/python/node.js。在此以go为例(主要原因go是我主要使用的开发语言)
CI/CD层Gitlab CI/CD、Gitlab-Runner
业务运营层组网设计要求:冗余架构、避免单点故障、业务流量独享网络
计算层:由PaaS层(k8s/istio组成)和镜像仓库(harbor)两部分组成
存储层:由ceph分布式存储组成
运维层基础支撑层:由DNS、os-w、DHCP、CA、web下载等服务组成
平台运维层:监,控采用promethues/grafana,日志ELK、Dashbord/rancher等
业务运维层:业务应用的后台基础管理,如mysql管理等
硬件运维层:主要是对硬件设备的管理,如服务器、网络设备、IaaS设备等等

提示:
1。在测试环境,在网络设计方面,只做功能性测试,不做冗余设计。
2。生产环境中需全链路冗余设计。
3。在生产中,设备选型时考虑到项目实际需求而进行架构设计。
4。所有节点时钟保持一致。

1.2 本文测试环境

1。网络192.168.3.1/24,电信300Mb。
2。cisco三层交换机一台,vlan3(192.168.3.1)、vlan20(10.2.20.20)、vlan10(10.2.20.10)。
3。HP DL360 Gen9一台, Xeon E5-2620。安装ESXi-8.0.0-20513097。
4。服务器nic1与交换机G0/1(Trunk模式)连接。

在这里插入图片描述

1.3 部署次序

项目简述
基础支撑层os-w服务、管理节点、DNS服务、CA服务、DHCP服务、web下载服务
CI/CD层 及镜像私仓1。安装Gitlab CI/CD、Gitlab Runner
2。安装harbor
存储层ceph安装
计算层k8s/istio安装
运维层监控采用promethues/grafana,日志ELK、Dashbord/rancher等
联调CI/CD测试、istio流量治理测试

二、基础支撑层

2.1 os-w服务

本文涉及到较多台服务器,都是基于os-w提供安装服务。

os-w是基于pxe协议而集成的系统,配合自开发的后台(go语言开发),可以完成企业内部的标准化系统管理,基于网络环境完成各类操作,可以有效减少IT运维人员的日常工作。拒绝本地操作、拒绝本地USB接口。

功能简述
1。标准化批量部署各类主流系统Redhat/Centos/Rocky/Ubuntu/Debian/ESXi/Windows等,支持主流X86服务器和PC。
2。针对windows安装,自动安装各类主流硬件驱动、支持预装应用软件(如office、outlook等)、自动加入域、自动激活。
4。支持自定义模板。
5。一键备份(某个分区或整个系统)到远程存储、从远程存储一键还原到本地。
6。EFI/BIOS双模式自动切换。
7。集成各类运维工具,满足linux/windows常规运维需求。

安装模式适应人员场景
单台安装无IT技能人员(新员工/普通员工),有引导菜单普通中大型企业、公司、事业单位等,员工自己安装系统,像喝水一样简单
批量安装IT运维人员(低IT技能),dhcp配置支持机房/IaaS环境中集群部署。如30分钟快速安装500台机器

提示:
本文不对os-w安装做详细介绍,如有需要,可直接联系我,大家共同学习。

2.2 管理节点

管理节点,主要用途是对系统中各类节点进行管理。
1。ceph各节点管理
2。k8s各节点管理
3。其它节点管理
采用密钥对ssh免密方式进行。

Rocky Linux release 9.1 (Blue Onyx)

基本工具包

yum -y install epel-release
yum -y install bash-completion net-tools gcc wget curl telnet tree lrzsz iproute bind-utils

安装ansible

yum -y install ansible

ssh密钥对配置

ssh-keygen

产生/root/.ssh/id_rsa.(私钥)和/root/.ssh/id_rsa.pub.(公钥)两个文件。
采用ssh-copy-id命令将公钥复制到目标机器。

提示:
后续配置中会对管理节点进行相关配置。

2.3 DNS服务配置

linux系统中开源的DNS服务器有很多,常用的有bind/powerdns/coredns/dnsmasq等。

其中bind是传统bind服务器,也支持windows.
32位
https://ftp.isc.org/isc/bind9/9.15.5/BIND9.15.5.x86.zip

64位
https://ftp.isc.org/isc/bind9/9.17.5/BIND9.17.5.x64.zip

在实际项目生产环境中都是采用linux安装DNS。

由于是demo,今天我们采用windows安装bind,感受一下bind9在windows环境下的情况。
下载https://ftp.isc.org/isc/bind9/9.15.5/BIND9.15.5.x86.zip解压后直接运行BINDInstall.exe即可完成安装。

下面配置样例中配置了demo.io、demo.com、test.com三个域名用来测试。

配置named.conf

options {directory "C:\Program Files\ISC BIND 9\etc";forwarders {8.8.8.8;223.6.6.6;    };   allow-query { any; };
};
zone "." IN {type hint;file "named.ca";
};zone "localhost" IN {type hint;file "localhost.zone";
};zone "0.0.127.in-addr.arpa" IN {type master;file "127.0.0.addr.arpa";allow-update { none;};
};zone "demo.com" IN {type master;file "demo.com.zone";allow-update { none;};
};zone "demo.io" IN {type master;file "demo.io.zone";allow-update { none;};
};zone "test.com" IN {type master;file "test.com.zone";allow-update { none;};
};

配置localhost.zone

$TTL 1D
@       IN      SOA     localhost.      root.localhost. (        2007091701          ; Serial30800               ; Refresh7200                ; Retry604800              ; Expire300 )               ; MinimumIN      NS      localhost.
localhost.        IN      A       127.0.0.1

配置demo.com.zone

demo.com.    IN  SOA   ns1.demo.com.  root.demo.com. (        2007091701         ; Serial30800              ; Refresh7200               ; Retry604800             ; Expire300 )              ; MinimumIN    NS        ns1.demo.com.
*       IN    A         192.168.110.10
test	IN	A	192.168.3.110
master1.k8s	IN	A	10.2.20.60
harbor	IN	A	10.2.20.70
git	IN	A	10.2.20.71
rancher	IN	A	10.2.20.151
grafana	IN	A	192.168.3.180
prometheus	IN	A	192.168.3.180
alert	IN	A	192.168.3.180
kiali	IN	A	192.168.3.182
prometheus-istio	IN	A	192.168.3.180
dashboard	IN	A	192.168.3.181

配置demo.io.zone

demo.io.    IN  SOA   ns1.demo.io.  root.demo.io. (        2007091701         ; Serial30800              ; Refresh7200               ; Retry604800             ; Expire300 )              ; MinimumIN    NS        ns1.demo.io.
*       IN    A         192.168.3.180
www	IN	A	192.168.3.180
master1.k8s	IN	A	10.2.20.60
harbor	IN	A	10.2.20.70
git	IN	A	10.2.20.71
rancher	IN	A	10.2.20.151
grafana	IN	A	192.168.3.180
prometheus	IN	A	192.168.3.180
alert	IN	A	192.168.3.180
kiali	IN	A	192.168.3.182
prometheus-istio	IN	A	192.168.3.180
dashboard	IN	A	192.168.3.181

配置test.com.zone

test.com.    IN  SOA   ns1.test.com.  root.test.com. (        2007091701         ; Serial30800              ; Refresh7200               ; Retry604800             ; Expire300 )              ; MinimumIN    NS        ns1.test.com.
*       IN    A         192.168.3.180
www	IN	A	192.168.3.180
master1.k8s	IN	A	10.2.20.60
harbor	IN	A	10.2.20.70
git	IN	A	10.2.20.71
rancher	IN	A	10.2.20.151
grafana	IN	A	192.168.3.180
prometheus	IN	A	192.168.3.180
alert	IN	A	192.168.3.180
kiali	IN	A	192.168.3.182
prometheus-istio	IN	A	192.168.3.180
dashboard	IN	A	192.168.3.181

启动服务

C:\>net start named
ISC BIND 服务正在启动 .
ISC BIND 服务已经启动成功。

测试

C:\>nslookup -q  www.demo.io 192.168.3.250
服务器:  UnKnown
Address:  192.168.3.250名称:    www.demo.io
Address:  192.168.3.180C:\>nslookup -q  www.demo.com 192.168.3.250
服务器:  UnKnown
Address:  192.168.3.250名称:    www.demo.com
Address:  192.168.110.10

提示:
DNS是基础设施,后续会调整相应记录解析。

2.4 CA证书配置

在实际生产中,SSL证书是必不可少的。
例如:在配置harbor时,使用了SSL证书。

我们需要配置相应的证书,测试时我们采用cfssl工具制作私有CA证书及签发证书。

官网地址: https://pkg.cfssl.org/
Github 地址: https://github.com/cloudflare/cfssl

2.4.1 cfssl工具安装

二进制安装

curl -s -L -o /bin/cfssl https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssl_1.6.4_linux_amd64
curl -s -L -o /bin/cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssljson_1.6.4_linux_amd64
curl -s -L -o /bin/cfssl-certinfo https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssl-certinfo_1.6.4_linux_amd64
chmod +x /bin/cfssl*

2.4.2 证书产生过程

第一步:产生根ca证书和私钥
配置根ca证书签名请求文件模板

# cat > ca-csr.json <<EOF
{"CN":"Root-CA","key":{"algo":"rsa","size":2048},"names":[{"C":"CN","L":"Gudong","ST":"shenzhen","O":"k8s","OU":"System"}]
}
EOF

使用根ca证书签名请求文件生成证书和私钥

cfssl gencert -initca ca-csr.json | cfssljson -bare ca 

输出三个文件

    ca.csr        //根证书请求文件ca-key.pem    //根证书私钥ca.pem        //根证书

第二步:产生用户证书
证书配置文件,有效期配置比较长为100年。

# cat ca-config.json
{"signing":{"default":{"expiry":"876000h"},"profiles":{"web-auth":{"expiry":"876000h","usages":["signing","key encipherment","server auth","client auth"]}}}
}

证书签发列表配置

# cat server-csr.json
{"CN":"domain-ssl-test","hosts":["127.0.0.1","localhost","*.test.com","*.test.io","*.demo.com","*.demo.io","*.gfs.com"],"key":{"algo":"rsa","size":2048},"names":[{"C":"CN","L":"HeNan","ST":"ZhuMaDian","O":"k8s","OU":"System"}]
}

签发证书

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=web-auth \
server-csr.json | cfssljson -bare web

产生的文件说明如下

# tree /root/cfssl
/root/cfssl
├── ca.csr            根ca证书签名请求文件
├── ca-csr.json       根ca证书签名请求文件模板
├── ca-key.pem        根证书私钥
├── ca.pem            根证书
├── ca-config.json    用户证书模板
├── server-csr.json   用户证书签发列表配置
├── web.csr           用户证书签发申请书
├── web-key.pem       用户证书私钥
└── web.pem           用户证书

实验配置中主要使用到ca.pem、web.pem、web-key.pem三个文件。
把它们放在web下载服务器上,供其它节点下载。

第三步:查验证书信息

# openssl x509 -noout -text -in  web.pem 
Certificate:Data:Version: 3 (0x2)Serial Number:16:e7:8c:e8:f5:3a:a4:bb:3d:6c:90:04:ac:d4:d9:50:03:ea:21:52Signature Algorithm: sha256WithRSAEncryptionIssuer: C = CN, ST = shenzhen, L = Gudong, O = k8s, OU = System, CN = Root-CA-gfsValidityNot Before: May 22 05:59:00 2023 GMTNot After : Apr 28 05:59:00 2123 GMTSubject: C = CN, ST = ZhuMaDian, L = HeNan, O = k8s, OU = System, CN = domain-ssl-testSubject Public Key Info:Public Key Algorithm: rsaEncryptionPublic-Key: (2048 bit)Modulus:00:c6:a9:45:9b:f2:e4:a1:43:b6:a8:5d:01:31:d9:13:d0:f3:e3:c6:a6:38:8f:bc:2b:6c:bc:8c:84:32:b5:16:22:85:dd:a1:a4:d6:87:a3:f3:91:66:4c:9b:3f:45:1d:6c:97:98:6e:fb:c5:a9:00:95:d5:5f:7d:86:de:26:34:bf:66:92:a8:57:39:c0:36:fb:12:b1:f8:c9:3b:3a:0c:7d:79:d7:10:5f:3d:ba:0e:3c:17:e7:08:45:23:58:cc:6f:d7:f3:3a:fb:4d:61:eb:92:e7:2b:d4:21:ce:7e:a7:32:00:e9:d5:58:f2:94:e6:ea:79:d9:7a:19:92:95:40:5c:f2:80:3c:57:b0:52:f2:ab:9c:d6:d7:9e:1b:fd:d6:d5:66:8d:27:d1:8d:b7:10:dc:a6:4d:ec:fb:21:71:e3:27:d2:b1:fb:f4:63:4d:86:ba:35:fb:7a:40:b2:b1:6d:c7:c5:e9:98:ac:8d:ab:36:2b:8e:79:9d:4a:fa:3a:c3:11:8f:2c:69:04:28:ac:ac:93:c7:bf:6c:a3:b7:32:b1:d0:a4:90:6f:63:2c:37:0e:94:43:d0:ed:9a:b3:e0:f9:ba:2d:18:86:7f:72:44:b3:1c:b0:8c:cb:b4:d1:9d:19:21:c3:48:8f:c9:6a:38:b8:c8:07:07:56:0a:49:e5:a4:5fExponent: 65537 (0x10001)X509v3 extensions:X509v3 Key Usage: criticalDigital Signature, Key EnciphermentX509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client AuthenticationX509v3 Basic Constraints: criticalCA:FALSEX509v3 Subject Key Identifier: CF:E0:D0:A9:3A:20:5C:B0:CD:AF:4C:C6:5B:51:E7:C4:CB:5F:E3:64X509v3 Authority Key Identifier: 78:69:9C:18:47:D1:D3:44:05:1F:20:A7:B2:FF:6A:E6:68:85:D3:48X509v3 Subject Alternative Name: localhost, DNS:*.test.com, DNS:*.demo.com, DNS:*.test.io, DNS:*.demo.io, DNS:*.gfs.com, IP Address:127.0.0.1Signature Algorithm: sha256WithRSAEncryptionSignature Value:5e:59:bc:88:39:1b:12:f6:13:5e:8e:d4:4a:78:1a:42:21:70:c4:1e:61:80:c1:64:01:6b:9e:06:55:3f:bd:f2:89:5c:7b:6b:2c:ff:9a:5a:79:45:61:a3:25:09:3f:9f:4f:45:ce:bd:8e:b6:8e:2c:1e:5b:9e:37:6e:26:83:59:1f:2f:42:04:36:d6:29:59:df:e2:17:e8:2e:3c:f1:12:bf:dd:d8:68:e9:3f:26:10:2d:10:2e:51:05:a8:b9:6b:e1:f4:08:06:ec:67:2f:91:b4:3c:c5:15:c2:10:21:a1:81:af:ce:4f:64:6b:46:b2:6a:6f:01:44:11:c6:91:67:f2:33:94:d3:76:a7:b9:29:ff:05:6c:8c:de:64:27:6e:dd:c6:17:51:1b:50:00:b4:5f:5e:54:52:31:92:84:53:92:3c:8c:58:c8:60:8a:28:89:dd:59:62:42:ff:1b:5f:82:7e:1d:39:e3:bd:22:d8:c5:d2:b8:82:73:89:66:43:a8:5a:0a:c1:6f:58:2c:a0:6e:c6:e2:6e:b5:d8:0e:30:28:b1:34:bf:e1:0d:bf:ee:b2:13:98:27:3f:09:43:f9:0f:87:d1:f4:a2:30:c1:de:71:31:cc:b1:10:cc:ff:7e:14:3a:ff:08:40:9a:fe:08:b6:83:89:e0:1e:ba:05:d9

可以查看到证书签发给localhost、.test.com、.test.io、.demo.com、.demo.io、*.gfs.com、127.0.0.1且有效期到2123年。

2.5 DHCP服务

在DHCP中需指定DNS和网关。
dhcp服务器安装

yum -y install dhcp-server
systemctl enable dhcpd.service

注意事项:
需在cisco三层交换机中配置dhcp relpy.
例如:

interface Vlan20ip address 10.2.20.254 255.255.255.0ip helper-address 192.168.3.246ip dhcp relay information trusted

2.6 web下载服务

在配置中,若有较多文件需在多个机器中配置,如证书文件,此时配置一个web下载服务会更方便一点。

yum -y install httpd
systemctl enable httpd.service
systemctl start httpd.service 
mkdir /var/www/html/ssl
cp {ca.pem,ca-key.pem,web-key.pem,web.pem} /var/www/html/ssl/

三、CI/CD层

此部分是DevOps敏捷开发理念的核心实现。

3.1 镜像仓库harbor

harbor资源
https://github.com/vmware/harbor/releases
https://github.com/goharbor/harbor/releases

很多公司提供了它们公开的容器 Registr 服务,比如

  1. Docker 官方的 Registry
  2. 亚马逊 ECR(Elastic Container Registry)
  3. Google云Registry
  4. Project Atomic
  5. JFrog Artifactory
  6. dockerhub
  7. harbor
  8. quay.io

其中harbor是VMware公司开源的DockerRegistry项目(https://github.com/vmware/harbor),其目标是帮助用户迅速搭建一个企业级的DockerRegistry服务,提供图形界面和权限控制。它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能.

3.1.1 安装前准备

主机基本信息

# hostname
image# cat /etc/redhat-release 
Rocky Linux release 9.1 (Blue Onyx)# ip addr | grep ens
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000inet 10.2.20.70/24 brd 10.2.20.255 scope global noprefixroute ens33
3: ens36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000inet 192.168.3.20/24 brd 192.168.3.255 scope global dynamic noprefixroute ens36

安装docker

yum -y install yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum -y install docker-ce docker-ce-cli containerd.io
systemctl enable docker containerd
systemctl start docker containerd

测试

# docker version
Client: Docker Engine - CommunityVersion:           23.0.2API version:       1.42Go version:        go1.19.7Git commit:        569dd73Built:             Mon Mar 27 16:19:13 2023OS/Arch:           linux/amd64Context:           defaultServer: Docker Engine - CommunityEngine:Version:          23.0.2API version:      1.42 (minimum version 1.12)Go version:       go1.19.7Git commit:       219f21bBuilt:            Mon Mar 27 16:16:18 2023OS/Arch:          linux/amd64Experimental:     falsecontainerd:Version:          1.6.20GitCommit:        2806fc1057397dbaeefbea0e4e17bddfbd388f38runc:Version:          1.1.5GitCommit:        v1.1.5-0-gf19387adocker-init:Version:          0.19.0GitCommit:        de40ad0

安装Docker-compose

# ver=v2.17.3
# curl -L https://github.com/docker/compose/releases/download/$ver/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
# docker-compose version
Docker Compose version v2.17.3

3.1.2 安装harbor

下载

# wget https://github.com/goharbor/harbor/releases/download/v2.8.1/harbor-offline-installer-v2.8.1.tgz
# tar zxvf harbor-offline-installer-v2.8.1.tgz 
# tree harbor
harbor
├── common.sh
├── harbor.v2.8.1.tar.gz
├── harbor.yml.tmpl       //配置文件模板,需“cp harbor.yml.tmpl harbor.yml”
├── install.sh            //安装脚本
├── LICENSE
└── prepare

配置harbor.yml

# cp harbor.yml.tmpl harbor.yml
# vi harbor.yml
hostname: harbor.demo.com		//配置访问域名和证书。
http:port: 80
https:port: 443certificate: /etc/ssl/test-ssl/web.pemprivate_key: /etc/ssl/test-ssl/web-key.pem
harbor_admin_password: 123qweasd+pp
database:password: root123
data_volume: /data/harbor

提示,需查将harbor.demo.com的证书复制到/etc/ssl/test-ssl/

安装harbor

# ./install.sh 
Note: docker version: 23.0.2
Note: Docker Compose version v2.17.2
Note: stopping existing Harbor instance ...
[+] Running 5/5✔ Container harbor-portal  Removed                                                                                                                                0.1s ✔ Container redis          Removed                                                                                                                                0.1s ✔ Container harbor-db      Removed                                                                                                                                0.1s ✔ Container harbor-log     Removed                                                                                                                                0.1s ✔ Network harbor_harbor    Removed                                                                                                                                0.3s [Step 5]: starting Harbor ...
[+] Running 10/10✔ Network harbor_harbor        Created                                                                                                                            0.3s ✔ Container harbor-log         Started                                                                                                                            2.1s ✔ Container registryctl        Started                                                                                                                            4.6s ✔ Container harbor-db          Started                                                                                                                            4.1s ✔ Container redis              Started                                                                                                                            4.1s ✔ Container harbor-portal      Started                                                                                                                            3.6s ✔ Container registry           Started                                                                                                                            4.4s ✔ Container harbor-core        Started                                                                                                                            5.2s ✔ Container harbor-jobservice  Started                                                                                                                            6.4s ✔ Container nginx              Started                                                                                                                            6.8s 
✔ ----Harbor has been installed and started successfully.----

查验

# docker ps
CONTAINER ID   IMAGE                                COMMAND                  CREATED       STATUS                 PORTS                                                                            NAMES
ea6ff7de2bd3   goharbor/harbor-jobservice:v2.8.1    "/harbor/entrypoint.…"   9 days ago    Up 6 hours (healthy)                                                                                    harbor-jobservice
51c3d360f8f7   goharbor/nginx-photon:v2.8.1         "nginx -g 'daemon of…"   9 days ago    Up 6 hours (healthy)   0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp   nginx
1d777e5c999c   goharbor/harbor-core:v2.8.1          "/harbor/entrypoint.…"   9 days ago    Up 6 hours (healthy)                                                                                    harbor-core
f37900962e2c   goharbor/harbor-registryctl:v2.8.1   "/home/harbor/start.…"   9 days ago    Up 6 hours (healthy)                                                                                    registryctl
64bf28a7ee91   goharbor/registry-photon:v2.8.1      "/home/harbor/entryp…"   9 days ago    Up 6 hours (healthy)                                                                                    registry
86f26071fac1   goharbor/harbor-db:v2.8.1            "/docker-entrypoint.…"   9 days ago    Up 6 hours (healthy)                                                                                    harbor-db
2988ed0c418f   goharbor/redis-photon:v2.8.1         "redis-server /etc/r…"   9 days ago    Up 6 hours (healthy)                                                                                    redis
f898c0d10656   goharbor/harbor-portal:v2.8.1        "nginx -g 'daemon of…"   9 days ago    Up 6 hours (healthy)                                                                                    harbor-portal
f99caa642448   goharbor/harbor-log:v2.8.1           "/bin/sh -c /usr/loc…"   9 days ago    Up 6 hours (healthy)   127.0.0.1:1514->10514/tcp                                                        harbor-log# ss -lnt
State       Recv-Q      Send-Q           Local Address:Port             Peer Address:Port      Process      
LISTEN      0           4096                 127.0.0.1:1514                  0.0.0.0:*                      
LISTEN      0           4096                   0.0.0.0:80                    0.0.0.0:*                      
LISTEN      0           32                     0.0.0.0:53                    0.0.0.0:*                      
LISTEN      0           128                    0.0.0.0:22                    0.0.0.0:*                      
LISTEN      0           4096                   0.0.0.0:443                   0.0.0.0:*                      
LISTEN      0           4096                      [::]:80                       [::]:*                      
LISTEN      0           128                       [::]:22                       [::]:*                      
LISTEN      0           4096                      [::]:443                      [::]:*                      
LISTEN      0           4096                         *:2375                        *:*       

重启harbor

# docker-compose start | stop | restart    //此命令的运行,依赖于安装目录中的docker-compose.yml文件。

3.1.3 访问测试

提示:在访问需要将私有CA的根证书添加到浏览器的根证书可信任区域。
在这里插入图片描述
在这里插入图片描述

3.1.4 镜像push和pull测试

可采用crictl/podman/docker等客户端工作都可以。

本测试临时安装一台测试机验,采用docker命令。

登录私有仓

下载证书
# wget http://10.2.20.59/ssl/ca.pem
加入根CA证书链
# cat ca.pem >> /etc/pki/tls/certs/ca-bundle.crt
登录私有仓
# docker login harbor.demo.com
Username: admin
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
#

push镜像到私有仓


下载一个镜像
# docker pull busybox:latest
latest: Pulling from library/busybox
325d69979d33: Pull complete 
Digest: sha256:560af6915bfc8d7630e50e212e08242d37b63bd5c1ccf9bd4acccf116e262d5b
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest修改tag
# docker tag busybox:latest harbor.demo.com/temp/busybox:latest上传到私有仓库
# docker push harbor.demo.com/temp/busybox:latest
The push refers to repository [harbor.demo.com/temp/busybox]
9547b4c33213: Pushed 
latest: digest: sha256:5cd3db04b8be5773388576a83177aff4f40a03457a63855f4b9cbe30542b9a43 size: 528

进入https://harbor.demo.com查看下
在这里插入图片描述

从私有仓拉取镜像到本地

查看镜像
# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED       SIZE
harbor.demo.com/temp/busybox   latest    8135583d97fe   12 days ago   4.86MB
busybox                        latest    8135583d97fe   12 days ago   4.86MB删除现有镜像
# docker image rm -f 8135583d97fe
Untagged: busybox:latest
Untagged: busybox@sha256:560af6915bfc8d7630e50e212e08242d37b63bd5c1ccf9bd4acccf116e262d5b
Untagged: harbor.demo.com/temp/busybox:latest
Untagged: harbor.demo.com/temp/busybox@sha256:5cd3db04b8be5773388576a83177aff4f40a03457a63855f4b9cbe30542b9a43
Deleted: sha256:8135583d97feb82398909c9c97607159e6db2c4ca2c885c0b8f590ee0f9fe90d
Deleted: sha256:9547b4c33213e630a0ca602a989ecc094e042146ae8afa502e1e65af6473db03查看镜像,为空
# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE从私有仓拉取镜像
# docker pull harbor.demo.com/temp/busybox:latest
latest: Pulling from temp/busybox
325d69979d33: Pull complete 
Digest: sha256:5cd3db04b8be5773388576a83177aff4f40a03457a63855f4b9cbe30542b9a43
Status: Downloaded newer image for harbor.demo.com/temp/busybox:latest
harbor.demo.com/temp/busybox:latest查看镜像
# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED       SIZE
harbor.demo.com/temp/busybox   latest    8135583d97fe   12 days ago   4.86MB

3.2 代码仓库Gitlab

gitlab(极狐)是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。Ruby on Rails 是一个可以使你开发、部署、维护 web 应用程序变得简单的框架。

GitLab拥有与Github类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。它还提供一个代码片段收集功能可以轻松实现代码复用,便于日后有需要的时候进行查找。

GitLab 分为如下两个版本
1.GitLab Community Edition(CE) 社区版。 社区版免费
2.GitLab Enterprise Edition(EE) 专业版。专业版收费

提示:
若在公网搭建gitlab服务,需开放http80、https443、ssh22三个端口。

3.2.1 安装及配置gitlab

gitlab安装方式有源码方式、yum方式、docker方式。
本测试采用yum方式安装。

安装gitlab

yum -y install epel-release  curl policycoreutils openssh-server openssh-clients
systemctl disable firewalld
systemctl stop firewalld
curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
yum -y install gitlab-ce
systemctl enable gitlab-runsvdir.service
systemctl start gitlab-runsvdir.service

配置https(/etc/gitlab/gitlab.rb),把证书复制到/etc/gitlab/ssl/(需新创建此目录)

# vi /etc/gitlab/gitlab.rb
external_url 'https://git.demo.com'
letsencrypt['enable'] = false
nginx['redirect_http_to_https'] = true
nginx['ssl_certificate'] = "/etc/gitlab/ssl/web.pem"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/web-key.pem"
# gitlab-ctl reconfigure查看gitlab版本
# cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
16.0.1查看gitlab管理员root初始密码
# cat /etc/gitlab/initial_root_password

访问https://git.demo.com
在这里插入图片描述
提示:
第一次进入后建议改密码

GitLab头像无法正常显示,可以配置如下

# vi /etc/gitlab/gitlab.rb
### Gravatar Settings
gitlab_rails['gravatar_plain_url'] = 'https://sdn.geekzu.org/avatar/%{hash}?s=%{size}&d=identicon'
gitlab_rails['gravatar_ssl_url'] = 'https://sdn.geekzu.org/avatar/%{hash}?s=%{size}&d=identicon'
# gitlab-ctl reconfigure

通知信息配置(邮件方式)

# vi /etc/gitlab/gitlab.rb
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "xxxxxxx@qq.com"
gitlab_rails['smtp_password'] = "oherqwzatxxxxxxxxj"
gitlab_rails['smtp_domain'] = "qq.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = false
gitlab_rails['smtp_tls'] = true
gitlab_rails['smtp_pool'] = true
gitlab_rails['gitlab_email_from'] = 'xxxxxxxxx@qq.com'
gitlab_rails['gitlab_email_display_name'] = 'Administrator'
gitlab_rails['gitlab_email_reply_to'] = 'xxxxxxxxxx@qq.com'
# gitlab-ctl reconfigure

测试

进入console
# gitlab-rails console
--------------------------------------------------------------------------------Ruby:         ruby 3.0.6p216 (2023-03-30 revision 23a532679b) [x86_64-linux]GitLab:       16.0.1 (34d6370bacd) FOSSGitLab Shell: 14.20.0PostgreSQL:   13.8
------------------------------------------------------------[ booted in 96.22s ]
Loading production environment (Rails 6.1.7.2)发测试邮件:如Notify.test_email('xxxxxxx@163.com','this is title','hello gitlab').deliver_nowirb(main):001:0> Notify.test_email('xxxxxxx@163.com','this is title','hello gitlab').deliver_now
Delivered mail 647965bb85fe7_21e4317463563@test.mail (959.0ms)
=> #<Mail::Message:291920, Multipart: false, Headers: <Date: Fri, 02 Jun 2023 11:44:59 +0800>, <From: Administrator <xxxxxxxxxxxxxxx@qq.com>>, <Reply-To: Administrator <xxxxxxxxxxxx@qq.com>>, <To: xxxxxxxxxxxx@163.com>, <Message-ID: <647965bb85fe7_21e4317463563@test.mail>>, <Subject: this is title>, <Mime-Version: 1.0>, <Content-Type: text/html; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>, <Auto-Submitted: auto-generated>, <X-Auto-Response-Suppress: All>>
irb(main):002:0> 
若能成功收到,说明配置是正常的。

创建新用户
在这里插入图片描述

3.2.1 测试

假如已创建用户guofs,并以guofs帐户创建了项目web.git

3.2.1.1 ssh方式

在用户机器上生成公钥和私钥(用于gitlab)

# ssh-keygen -t rsa -C "guofs@163.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:AP1rvv6ySqYAwZeXQb7AXCvOFx2riAwToptIV++DixI guofs@163.com
The key's randomart image is:
+---[RSA 2048]----+
|o   o* .         |
|+.o =.B o        |
|=o O *.=         |
|==* = *..        |
|=E + = oS.       |
| .. o . +        |
| ... .oo         |
|  .. +  o        |
|    . .o+=.      |
+----[SHA256]-----+
# cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAQSNJDMRjORJ599Ez6qdYpKh8V7L+TWv3kqkqxTmJf0ijEvdG/NqPAuC1QqswMlRVb8Zlu1hYawCYfF2FTQUnxW7dvgUXkbxaUvYBacarG/3ewVoa60+9w/kQFNyQsndt4BCYy8G0XsZfB1OmqFlErgQogHAGyau+CF3Fa8yY5j8b5dbHwtR9Yhrs3wyQlNuluU4TAAHTBMDQ6XkAagc53lAbz8VOF7NUbcDMXQ3EdZ74gYHh/RygS003gE+pNSoON+QX9y2uDmPWZQyB0ouRlqRpQx7taxq/nFva3bq55gCIzLAD52CotKeEPnHjEBnhUOAqMo8BIoMVs4Wl8mk5 guofs@163.com

将id_rsa.pub公钥复制到gitlab
在这里插入图片描述

clone项目

# git clone -b main git@git.demo.com:guofs/web.git
Cloning into 'web'...
The authenticity of host 'git.demo.com (10.2.20.36)' can't be established.
ED25519 key fingerprint is SHA256:KDdQTbTJm1fCmC0n3RrNmCJXGBBzXehOQbm4j31tYNg.
This host key is known by the following other names/addresses:~/.ssh/known_hosts:65: 10.2.20.36
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'git.demo.com' (ED25519) to the list of known hosts.
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.# tree web -a -L 2
web
|-- .git
|   |-- HEAD
|   |-- branches
|   |-- config
|   |-- description
|   |-- hooks
|   |-- index
|   |-- info
|   |-- logs
|   |-- objects
|   |-- packed-refs
|   `-- refs
`-- README.md

push代码

# cd web
# git config user.name "Darry.Guo"
# git config user.email "guofs@139.com"
# date >> 1.txt
# git add *
# git commit -m "11"
[main d4a8520] 111 file changed, 1 insertion(+)
# git push git@git.demo.com:guofs/web.git main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 301 bytes | 301.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To git.demo.com:guofs/web.gitb492ec7..d4a8520  main -> main

3.2.1.2 http/https方式

使用guofs进入https://git.demo.com创建token值。
例如:glpat-nC7mYxxfTdJQEJLuGpsR
在这里插入图片描述

clone项目

# git clone -b main https://git.demo.com/guofs/web.git
Cloning into 'web'...
Username for 'https://git.demo.com': guofs
Password for 'https://guofs@git.demo.com': 	//此处录入token值
remote: Enumerating objects: 12, done.
remote: Counting objects: 100% (12/12), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 12 (delta 1), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (12/12), done.
Resolving deltas: 100% (1/1), done.

push代码

# cd web
# git config user.name "Darry.Guo"
# git config user.email "guofs@139.com"
# date >> 1.txt
# git add *
# git commit -m "11"
[main d4a8520] 111 file changed, 1 insertion(+)
# git push https://git.demo.com/guofs/web.git main
Username for 'https://git.demo.com': guofs
Password for 'https://guofs@git.demo.com': 	//此处录入token值
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes | 308.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
To https://git.demo.com/guofs/web.git10e3dec..347fa15  main -> main

3.3 配置Gitlab CI/CD、Gitlab Runner

持续集成(Continuous Integration)、持续交付(Continuous Delivery)是敏捷开发体现。
可以采用jenkins实现,也可以使用gitlab提供的CI/CD来实现。采用gitlab CI/CD时,主要分为四步
其一:安装gitlab runner
其二:通过gitlab runner向CI/CD注册各类executor。executor体具执行pipeline动作。executor不同,其执行的动作不相同。某个executor只完成特定动作。
其三:编写.gitlab-ci.yml
其四:Gitlab CI/CD依据.gitlab-ci.yml开展工作。CI/CD通过过push/merge/trigger等多种动作执行pipeline.

3.3.1 安装 Gitlab Runner

官网:https://docs.gitlab.com/runner/
runner安装在独立机器上或采用docker方式安装。
本文以docker方式安装为例。

# docker pull gitlab/gitlab-runner# docker images
REPOSITORY             TAG       IMAGE ID       CREATED         SIZE
gitlab/gitlab-runner   latest    4575ef0329b0   2 weeks ago     749MB# docker run -itd --restart=always  \
--name gitlab-runner \
-v /etc/gitlab-runner:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock  \
gitlab/gitlab-runner:latest说明:
-v $HOME/gitlab-runner/config:/etc/gitlab-runner:
这个挂载是将gitlab-runner的配置文件挂载到宿主机上,这样我们可以通过修改宿主机上的这个配置文件对gitlab-runner进行配置
-v /var/run/docker.sock:/var/run/docker.sock:
这个挂载是将宿主机上的docker socket挂载到了容器内,这样容器内执行的docker命令会被宿主机docker daemon最终执行。
此操作是为Executor Docker时做准备工作。
这两个挂载很关健进入容器
# docker exec -it gitlab-runner /bin/bash		//可以在容器内部做注册工作。
root@7a8453ddab09:/# gitlab-runner -h

3.3.2 注册runner executor/docker-in-docker

executor是gitlab CI的重要概念,不同的executor完成不同的动作,比如:不同开发语言的源码编译需不同的executor,不同的 executor可以让应用部署在物理节点、虚拟机、docker容器、或k8s中的pod等。

executor被runner注册到gitlab CI中,每个注册成功的executor都有一个tag,配置.gitlab-ci.yml凭tag对executor进行调用。

runner有如下3种情况

类型说明
共享级runner供所有项目使用
群组级runner供群组成员中的项目使用
项目级runner仅供本项目使用

本文采用docker-in-docker方式。
目标:创建一个executor,用于编译go源码,并将编译后的应用打包成镜像上传到私有仓库harbor.demo.com中。

提示:
在此docker-in-docker时采用了一个自制镜像存于私仓harbor.demo.com/cicd/centos8.5-tool:v0.2,它是基于centos8.5制作,其中安装也测试所需的软件,如docker客户端、go、curl等等。

进入容器gitlab-runner

# docker exec -it gitlab-runner /bin/bash

注册runner到Gitlab CI

root@7a8453ddab09:/# gitlab-runner register \
--url http://git.demo.com \
--registration-token GR13489413ocr9Hnhx-eTHAbcNCXx \
--tag-list docker-in-docker-test-1 \
--description "docker-in-docker-test-1" \
--maintenance-note "docker-in-docker-test-1" \
--executor docker \
--docker-pull-policy if-not-present \
--docker-helper-image "harbor.demo.com/cicd/gitlab-runner-helper:x86_64-dcfb4b66" \
--docker-image "harbor.demo.com/cicd/centos8.5-tool:v0.2" \
--docker-volumes /var/run/docker.sock:/var/run/docker.sock \
--env 'DOCKER_AUTH_CONFIG={"auths":{"harbor.demo.com":{"auth":"YWRtaW46MTJxd2FzenhvcGtsbm0="}}}'

说明:
其中–docker-helper-image和–docker-image这两个镜像,都是由gitlab服务器从私有仓库上面下载,因此需配置如下:

1。私有仓库采用https时,需将证书追回到gitlab服务器所在的/etc/ssl/certs/ca-certificates.crt文件中。2。有密码时,需配置--env参数,如下。--env 'DOCKER_AUTH_CONFIG={"auths":{"harbor.demo.com":{"auth":"YWRtaW46MTJxd2FzenhvcGtsbm0="}}}'其中用户名称和密码需采用如下办法输出:# printf "admin:12qwaszxopklnm" | openssl base64 -A此处配置的变量DOCKER_AUTH_CONFIG值本质是一个json字串,如下:{"auths": {"harbor.demo.com": {"auth": "YWRtaW46MTJxd2FzenhvcGtsbm0="}}}3。这两个镜像的pull规则:--docker-pull-policy {never, if-not-present, always}默认是always

查看注册情况

root@7a8453ddab09:/# gitlab-runner list
Runtime platform                                    arch=amd64 os=linux pid=51 revision=dcfb4b66 version=15.10.1
docker-in-docker-test-1                             Executor=docker Token=uyyzkGqaTayfRsJ8yJxg URL=http://git.demo.com

此runner可以编译go并可访问harbor.demo.com私有仓库。

3.3.3 编写.gitlab-ci.yml

采用GoLand编写一段测试代码,如下:
在这里插入图片描述
创建CI/CD流水文件.gitlab-ci.yml,如下

#全局变量赋值
variables:image_name: "busybox"#image_name: "centos"image_ver: "v2.1"#定义stages
stages:- build- push_image- test- deploy#job1:编译go源码为二进制文件
#局部变量Is_Run默认值为yes,则在push时会执行此任务。
job1:variables:Is_Run: "yes"stage: buildscript:- echo "build the code..."- export GOROOT=/usr/local/go- export PATH=$PATH:/usr/local/go/bin- export GOPATH=/opt- export GO115MODULE=on- export GOOS=linux- export GOARCH=amd64- export GOPROXY="https://goproxy.cn,direct"- go version- go mod tidy- go build -o app .- mkdir build- mv app build/- mv Dockerfile_nobuild build/Dockerfileartifacts:paths:- buildtags:- docker-in-docker-test-1rules:- if: $Is_Run == "yes"#job2的工作是将job1生成的应用打包上镜像,并push到私有仓库。
#局部变量Is_Run默认值为yes,则在push时会执行此任务。
#提示:$UserName和$PassWord是在gitlab项目定义的项目级变量,用于存放私有仓库的用户名和密码
job2:variables:Is_Run: "yes"stage: push_imageneeds:- job: job1artifacts: truescript:- echo "build image and push harbor register ..."- cd build/- ls -l- docker build -t harbor.demo.com/web/$image_name:$image_ver .- docker logout harbor.demo.com- echo $PassWord | base64 -d | docker login --username $UserName  --password-stdin harbor.demo.com- docker push harbor.demo.com/web/$image_name:$image_ver- docker rmi harbor.demo.com/web/$image_name:$image_vertags:- docker-in-docker-test-1rules:- if: $Is_Run == "yes"#job3的任务是测试应用。
#局部变量Is_Run默认值为yes,则在push时会执行此任务。通常开发过程中测试。
job3:variables:Is_Run: "yes"deploy_svc_name: "app-test"stage: testscript:- echo "deploy_to_k8s, $deploy_svc_name, http://www.test.com ..."tags:- docker-in-docker-test-1rules:- if: $Is_Run == "yes"#job4的任务用于发布
#局部变量Is_Run默认值为no,则在push时不会执行此任务,执行条件为:$Is_Run == "deploy"。
#需通过webhook方式执行此任务。通常用于在OA工作流中供领导审批是否正式发布此应用。
job4:variables:Is_Run: "no"deploy_svc_name: "app-demo-io"stage: deployscript:- echo "deploy_to_k8s, $deploy_svc_name, http://www.demo.io ..."tags:- docker-in-docker-test-1rules:- if: $Is_Run == "deploy"

此.gitlab-ci.yml有4个job,每个job定义有runner executor,采用tag来指定runner的tag标识。每个job可以有不同的runner,本例中采用相同的runner.

runner executor可以处理java/node.js/python/c/c++/php/go等多种语言,同时可以部署应用于物理服务、云主机、容器、k8s/istio中。

此步测试仅用于流程测试,在最后测试将应用发布在k8s中。

3.3.4 CI/CD测试

Gitlab CI/CD默认是启动,只要有“.gitlab-ci.yml”文件,会自动触发pipeline。
通常有两种方式来触发CI/CD流。
其一:push/merge动作
其二:采用webhook方式。

3.3.4.1 配置变量及webhok token

定义变量UserName和PassWord用于存储私有仓库的用户名称和密码。
在这里插入图片描述
定义webhook使用的token值。
在这里插入图片描述

3.3.4.2 push测试

push源码

git add *
git commit -m "test-1"
git push http://git.demo.com/guofs/cicdtest.git main

查看CI/CD变过程
在这里插入图片描述
可以查看每一个job的详细过程。例如job2.
在这里插入图片描述
查看镜像私有仓库
在这里插入图片描述

3.3.4.3 webhook测试

从配置上看,job4可以采用webhook方式赋值Is_Run=deploy来执行。
此步可通过OA流来调用,让领导通过工作流方式来审批此应用是否正式发布。

curl -X POST \--fail \-F token=glptt-938d9966afdc10180540a775d6e5e399fcd2cea0 \-F ref=main \-F "variables[Is_Run]=deploy" \-F "variables[deploy_svc_name]=demo-io-test" \http://git.demo.com/api/v4/projects/8/trigger/pipeline

查看
在这里插入图片描述
查看job详细

$ echo "deploy_to_k8s, $deploy_svc_name, http://www.demo.io ..."
deploy_to_k8s, demo-io-test, http://www.demo.io ...

四、存储层/ceph分布式存储

存储层采用ceph分布式存储,可提供块存储、对像存储、文件存储等多种方式。
并给k8s提供后端sc支持。

ceph测试环境如下,若是生产环境,需每个进程角色配置主备方式。

节点os配置ip角色
mgmRocky9.12vCPU,RAM2GB,HD:8GB10.2.20.59/192.168.3.x管理节点,ssh免密
ceph-mon1centos8.5.21112vCPU,RAM2GB,HD:8GB10.2.20.90/192.168.3.xmon,mgr,mds,dashboard,rgw
ceph-node1centos8.5.21112vCPU,RAM2GB,HD:8GB+10GBx210.2.20.91/192.168.3.xosd
ceph-node2centos8.5.21112vCPU,RAM2GB,HD:8GB+10GBx210.2.20.92/192.168.3.xosd
ceph-node3centos8.5.21112vCPU,RAM2GB,HD:8GB+10GBx210.2.20.93/192.168.3.xosd

ceph采用version 17.2.6 quincy (stable)。

采用os-w安装上述5台主机。

4.1 基本配置

4.1.1 所有节点基本配置

#配置hosts文件
cat >> /etc/hosts << 'EOF'
10.2.20.90      ceph-mon1
10.2.20.91      ceph-node1
10.2.20.92      ceph-node2
10.2.20.93      ceph-node3
EOF#安装基础软件
cd /etc/yum.repos.d/
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
rm -fr Centos8-2111*
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
yum clean all 
yum makecache
yum install -y epel-release
yum -y install net-tools wget bash-completion lrzsz unzip zip tree#关闭防火墙和selinux
systemctl disable --now firewalld
systemctl stop firewalld
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

ceph-17.2.6安装源

cat> /etc/yum.repos.d/ceph.repo << 'EOF'
[ceph]
name=Ceph packages for $basearch
baseurl=https://download.ceph.com/rpm-17.2.6/el8/$basearch
enabled=1
priority=2
gpgcheck=1
gpgkey=https://download.ceph.com/keys/release.asc[ceph-noarch]
name=Ceph noarch packages
baseurl=https://download.ceph.com/rpm-17.2.6/el8/noarch
enabled=1
priority=2
gpgcheck=1
gpgkey=https://download.ceph.com/keys/release.asc[ceph-source]
name=Ceph source packages
baseurl=https://download.ceph.com/rpm-17.2.6/el8/SRPMS
enabled=0
priority=2
gpgcheck=1
gpgkey=https://download.ceph.com/keys/release.asc
EOF

查看ceph安装包

# yum list Ceph*
Repository extras is listed more than once in the configuration
Last metadata expiration check: 0:01:01 ago on Mon 24 Apr 2023 10:22:10 PM CST.
Installed Packages
ceph-release.noarch                                  1-1.el8                @System    
Available Packages
ceph.x86_64                                          2:17.2.6-0.el8         ceph       
ceph-base.x86_64                                     2:17.2.6-0.el8         ceph       
ceph-base-debuginfo.x86_64                           2:17.2.6-0.el8         ceph       
ceph-common.x86_64                                   2:17.2.6-0.el8         ceph       
ceph-common-debuginfo.x86_64                         2:17.2.6-0.el8         ceph       
ceph-debuginfo.x86_64                                2:17.2.6-0.el8         ceph       
ceph-debugsource.x86_64                              2:17.2.6-0.el8         ceph       
ceph-exporter.x86_64                                 2:17.2.6-0.el8         ceph       
ceph-exporter-debuginfo.x86_64                       2:17.2.6-0.el8         ceph       
ceph-fuse.x86_64                                     2:17.2.6-0.el8         ceph       
ceph-fuse-debuginfo.x86_64                           2:17.2.6-0.el8         ceph       
ceph-grafana-dashboards.noarch                       2:17.2.6-0.el8         ceph-noarch
ceph-immutable-object-cache.x86_64                   2:17.2.6-0.el8         ceph       
ceph-immutable-object-cache-debuginfo.x86_64         2:17.2.6-0.el8         ceph       
ceph-mds.x86_64                                      2:17.2.6-0.el8         ceph       
ceph-mds-debuginfo.x86_64                            2:17.2.6-0.el8         ceph       
ceph-mgr.x86_64                                      2:17.2.6-0.el8         ceph       
ceph-mgr-cephadm.noarch                              2:17.2.6-0.el8         ceph-noarch
ceph-mgr-dashboard.noarch                            2:17.2.6-0.el8         ceph-noarch
ceph-mgr-debuginfo.x86_64                            2:17.2.6-0.el8         ceph       
ceph-mgr-diskprediction-local.noarch                 2:17.2.6-0.el8         ceph-noarch
ceph-mgr-k8sevents.noarch                            2:17.2.6-0.el8         ceph-noarch
ceph-mgr-modules-core.noarch                         2:17.2.6-0.el8         ceph-noarch
ceph-mgr-rook.noarch                                 2:17.2.6-0.el8         ceph-noarch
ceph-mon.x86_64                                      2:17.2.6-0.el8         ceph       
ceph-mon-debuginfo.x86_64                            2:17.2.6-0.el8         ceph       
ceph-osd.x86_64                                      2:17.2.6-0.el8         ceph       
ceph-osd-debuginfo.x86_64                            2:17.2.6-0.el8         ceph       
ceph-prometheus-alerts.noarch                        2:17.2.6-0.el8         ceph-noarch
ceph-radosgw.x86_64                                  2:17.2.6-0.el8         ceph       
ceph-radosgw-debuginfo.x86_64                        2:17.2.6-0.el8         ceph       
ceph-resource-agents.noarch                          2:17.2.6-0.el8         ceph-noarch
ceph-selinux.x86_64                                  2:17.2.6-0.el8         ceph       
ceph-test.x86_64                                     2:17.2.6-0.el8         ceph       
ceph-test-debuginfo.x86_64                           2:17.2.6-0.el8         ceph       
ceph-volume.noarch                                   2:17.2.6-0.el8         ceph-noarch
cephadm.noarch                                       2:17.2.6-0.el8         ceph-noarch
cephfs-mirror.x86_64                                 2:17.2.6-0.el8         ceph       
cephfs-mirror-debuginfo.x86_64                       2:17.2.6-0.el8         ceph       
cephfs-top.noarch                                    2:17.2.6-0.el8         ceph-noarch

4.1.2 管理节点

免密配置

ssh-keygen -t rsa
ssh-copy-id root@ceph-mon1
ssh-copy-id root@ceph-node1
ssh-copy-id root@ceph-node2
ssh-copy-id root@ceph-node3

配置ansible

# yum -y install ansible
# vi /etc/ansible/hosts 
[ceph]
ceph-mon1
ceph-node1
ceph-node2
ceph-node3
# ansible ceph -m shell -a "date"
ceph-mon1 | CHANGED | rc=0 >>
Sat Jun  3 22:32:43 CST 2023
ceph-node3 | CHANGED | rc=0 >>
Sat Jun  3 22:32:43 CST 2023
ceph-node1 | CHANGED | rc=0 >>
Sat Jun  3 22:32:43 CST 2023
ceph-node2 | CHANGED | rc=0 >>
Sat Jun  3 22:32:43 CST 2023

安装ceph等客户端命令

# yum -y install ceph-common ceph-base
# ceph -v
ceph version 17.2.6 (d7ff0d10654d2280e08f1ab989c7cdf3064446a5) quincy (stable)

4.1.3 ceph集群节点

# ansible ceph -m shell -a "yum -y install net-tools gdisk lvm2"
# ansible ceph -m shell -a "yum -y install ceph"# ansible ceph -m shell -a "systemctl list-unit-files | grep ceph"
...
ceph-crash.service                         enabled  
ceph-mds@.service                          disabled 
ceph-mgr@.service                          disabled 
ceph-mon@.service                          disabled 
ceph-osd@.service                          disabled 
ceph-volume@.service                       disabled 
ceph-mds.target                            enabled  
ceph-mgr.target                            enabled  
ceph-mon.target                            enabled  
ceph-osd.target                            enabled  
ceph.target                                enabled  
# ansible ceph -m shell -a "ceph -v"
ceph-mon1 | CHANGED | rc=0 >>
ceph version 17.2.6 (d7ff0d10654d2280e08f1ab989c7cdf3064446a5) quincy (stable)
ceph-node1 | CHANGED | rc=0 >>
ceph version 17.2.6 (d7ff0d10654d2280e08f1ab989c7cdf3064446a5) quincy (stable)
ceph-node3 | CHANGED | rc=0 >>
ceph version 17.2.6 (d7ff0d10654d2280e08f1ab989c7cdf3064446a5) quincy (stable)
ceph-node2 | CHANGED | rc=0 >>
ceph version 17.2.6 (d7ff0d10654d2280e08f1ab989c7cdf3064446a5) quincy (stable)

每个节点 工作目录

# tree /var/lib/ceph
/var/lib/ceph
├── bootstrap-mds
├── bootstrap-mgr
├── bootstrap-osd
├── bootstrap-rbd
├── bootstrap-rbd-mirror
├── bootstrap-rgw
├── crash
│   └── posted
├── mds
├── mgr
├── mon
├── osd
└── tmp

所有节点,ceph日志目录:/var/log/ceph

4.2 管理机点配置

管理节点主要功能是管理ceph集群,包括配置文件的产生、及使用ceph命令直接访问集群。

为方便配置,在管理节点上建立一个目录,用于存放ceph集群配置过程中产生的文件,默认在此目录中产生各类配置文件,并在需要时同步到ceph各节点。例如:

# mkdir /root/ceph
# cd /root/ceph

4.2.1 ceph集群全局唯一性标识配置

# uuidgen
9b7095ab-5193-420c-b2fb-2d343c57ef52
# ansible ceph -m shell -a "echo export cephuid=9b7095ab-5193-420c-b2fb-2d343c57ef52 >> /etc/profile"
# ansible ceph -m shell -a "source /etc/profile"
# ansible ceph -m shell -a "cat /etc/profile | grep cephuid"
ceph-node1 | CHANGED | rc=0 >>
export cephuid=9b7095ab-5193-420c-b2fb-2d343c57ef52
ceph-mon1 | CHANGED | rc=0 >>
export cephuid=9b7095ab-5193-420c-b2fb-2d343c57ef52
ceph-node3 | CHANGED | rc=0 >>
export cephuid=9b7095ab-5193-420c-b2fb-2d343c57ef52
ceph-node2 | CHANGED | rc=0 >>
export cephuid=9b7095ab-5193-420c-b2fb-2d343c57ef52

4.2.2 keyring配置

ceph-authtool --create-keyring ./ceph.client.admin.keyring --gen-key -n client.admin --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow *' --cap mgr 'allow *'
ceph-authtool --create-keyring ./ceph.mon.keyring --gen-key -n mon. --cap mon 'allow *'
ceph-authtool --create-keyring ./ceph.keyring --gen-key -n client.bootstrap-osd --cap mon 'profile bootstrap-osd' --cap mgr 'allow r'

4.2.3 ceph.conf初始配置

# cat > /root/ceph/ceph.conf <<EOF
[global]
fsid = 9b7095ab-5193-420c-b2fb-2d343c57ef52
public network = 10.2.20.0/24
auth cluster required = cephx
auth service required = cephx
auth client required = cephx
osd journal size = 1024
osd pool default size = 3
osd pool default min size = 2
osd pool default pg num = 32
osd pool default pgp num = 32
osd crush chooseleaf type = 0
mon_host = 10.2.20.90
mon_max_pg_per_osd = 1000[client.admin]
#mon host = 10.2.20.90
keyring = /etc/ceph/ceph.client.admin.keyring
EOF

4.2.4 客户端ceph命令配置

当ceph集群正常工作后,就可以使用ceph命令在管理节点上对集群进行管理。
建立在所有节点包括管理节点配置。
管理节点

# cp ceph.client.admin.keyring /etc/ceph/
# cp ceph.conf /etc/ceph/

ceph工作节点

ansible ceph -m copy -a "src=ceph.conf dest=/etc/ceph/"
ansible ceph -m copy -a "src=ceph.client.admin.keyring dest=/etc/ceph/"

在ceph集群建立后,可以在每个节点上使用ceph命令对ceph进行管理。

4.3 mon进程配置

在管理机上,在配置文件/root/ceph/ceph.conf中添加如下信息

[mon]
mon initial members = mon1
mon allow pool delete = true

并更新到各个节点

ansible ceph -m copy -a "src=ceph.conf dest=/etc/ceph/"

4.3.1 ceph.mon.keyring

把administrator keyring和bootstrap-osd keyring添加到中ceph.mon.keyring。

ceph-authtool ./ceph.mon.keyring --import-keyring ./ceph.client.admin.keyring
ceph-authtool ./ceph.mon.keyring --import-keyring ./ceph.keyring

将mon.keyring文件复制到所有mon节点,并配置权限

# scp ceph.mon.keyring ceph-mon1:/tmp/
# ssh ceph-mon1 "chown ceph:ceph /tmp/ceph.mon.keyring"

4.3.2 monitor map配置

# monmaptool --create --add mon1 10.2.20.90 --fsid $cephuid /root/ceph/monmap
monmaptool: monmap file /root/ceph/monmap
setting min_mon_release = octopus
monmaptool: set fsid to 9b7095ab-5193-420c-b2fb-2d343c57ef52
monmaptool: writing epoch 0 to /root/ceph/monmap (1 monitors)
# scp monmap ceph-mon1:/tmp/
# ssh ceph-mon1 "chown ceph:ceph /tmp/monmap"

4.3.3 创建monitor数据目录

在ceph-mon1节点上操作

# sudo -u ceph ceph-mon --mkfs -i mon1 --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring
# tree /var/lib/ceph/mon/ceph-mon1
/var/lib/ceph/mon/ceph-mon1
├── keyring
├── kv_backend
└── store.db├── 000004.log├── CURRENT├── IDENTITY├── LOCK├── MANIFEST-000003└── OPTIONS-000006

4.3.4 启动monitor服务

在ceph-mon1上配置开机启动

# systemctl enable ceph-mon@mon1
# systemctl start ceph-mon.target
# ss -lnt
State    Recv-Q   Send-Q     Local Address:Port       Peer Address:Port   Process   
LISTEN   0        128           10.2.20.90:6789            0.0.0.0:*                
LISTEN   0        128              0.0.0.0:22              0.0.0.0:*                
LISTEN   0        128                 [::]:22                 [::]:*                
# ceph config set mon auth_allow_insecure_global_id_reclaim false
# ps -ef | grep ceph-mon
ceph        1106       1  0 08:11 ?        00:00:02 /usr/bin/ceph-mon -f --cluster ceph --id mon1 --setuser ceph --setgroup ceph

查看

# ceph mon stat
e2: 1 mons at {mon1=[v2:10.2.20.90:3300/0,v1:10.2.20.90:6789/0]} removed_ranks: {}, election epoch 7, leader 0 mon1, quorum 0 mon1
# ceph -scluster:id:     9b7095ab-5193-420c-b2fb-2d343c57ef52health: HEALTH_WARN1 monitors have not enabled msgr2services:mon: 1 daemons, quorum mon1 (age 39m)mgr: no daemons activeosd: 0 osds: 0 up, 0 indata:pools:   0 pools, 0 pgsobjects: 0 objects, 0 Busage:   0 B used, 0 B / 0 B availpgs:         

4.4 mgr进程配置

在ceph-mon1节点上操作。

4.4.1 配置mgr服务

yum -y install ceph-mgr*
mgr_name='mgr1'
mkdir /var/lib/ceph/mgr/ceph-${mgr_name}
ceph auth get-or-create mgr.${mgr_name} mon 'allow profile mgr' osd 'allow *' mds 'allow *' > /var/lib/ceph/mgr/ceph-${mgr_name}/keyring
chown ceph:ceph -R /var/lib/ceph/mgr/ceph-${mgr_name}
ceph mon enable-msgr2

将如下内容添加到管理节点/root/ceph/ceph.conf文件

[mgr.mgr1]
# mon host = 10.2.20.90
keyring =  /var/lib/ceph/mgr/ceph-mgr1/keyring 

更新配置文件

ansible ceph -m copy -a "src=ceph.conf dest=/etc/ceph/"

启动ceph-mgr守护程序:

# systemctl enable ceph-mgr@mgr1
# systemctl start ceph-mgr.target     

查看mgr是否启动

# ps -ef | grep mgr
ceph        2059       1 78 09:16 ?        00:00:20 /usr/bin/ceph-mgr -f --cluster ceph --id mgr1 --setuser ceph --setgroup ceph
root        2205    1677  0 09:16 pts/0    00:00:00 grep --color=auto mgr
# ceph -scluster:id:     9b7095ab-5193-420c-b2fb-2d343c57ef52health: HEALTH_OKservices:mon: 1 daemons, quorum mon1 (age 7m)mgr: mgr1(active, since 9s)osd: 0 osds: 0 up, 0 indata:pools:   0 pools, 0 pgsobjects: 0 objects, 0 Busage:   0 B used, 0 B / 0 B availpgs:   
# ss -lntp
State   Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process                               
LISTEN  0        128           10.2.20.90:6800          0.0.0.0:*      users:(("ceph-mgr",pid=2059,fd=30))  
LISTEN  0        128           10.2.20.90:6801          0.0.0.0:*      users:(("ceph-mgr",pid=2059,fd=31))  
LISTEN  0        128              0.0.0.0:22            0.0.0.0:*      users:(("sshd",pid=1024,fd=4))       
LISTEN  0        128           10.2.20.90:3300          0.0.0.0:*      users:(("ceph-mon",pid=1106,fd=27))  
LISTEN  0        128           10.2.20.90:6789          0.0.0.0:*      users:(("ceph-mon",pid=1106,fd=28))  
LISTEN  0        128                 [::]:22               [::]:*      users:(("sshd",pid=1024,fd=6))  

4.4.2 配置mgr模块

查看mgr模块

# ceph mgr module ls
MODULE                              
balancer              on (always on)
crash                 on (always on)
devicehealth          on (always on)
orchestrator          on (always on)
pg_autoscaler         on (always on)
progress              on (always on)
rbd_support           on (always on)
status                on (always on)
telemetry             on (always on)
volumes               on (always on)
iostat                on            
nfs                   on            
restful               on            
alerts                -             
cephadm               -             
dashboard             -             
diskprediction_local  -             
influx                -             
insights              -             
k8sevents             -             
localpool             -             
mds_autoscaler        -             
mirroring             -             
osd_perf_query        -             
osd_support           -             
prometheus            -             
rook                  -             
selftest              -             
snap_schedule         -             
stats                 -             
telegraf              -             
test_orchestrator     -             
zabbix                -         

启用prometheus

ceph mgr module enable prometheus

查看prometheus采集指标
http://10.2.20.90:9283/metrics

4.4.2 配置mgr模块dashbord

将域名证书复制到/etc/ceph/cert/目录

ceph mgr module enable dashboard
ceph dashboard set-ssl-certificate -i /etc/ceph/cert/web.pem
ceph dashboard set-ssl-certificate-key -i /etc/ceph/cert/web-key.pem
echo "abc123xyz" > pwd.txt
ceph dashboard ac-user-create admin -i ./pwd.txt administrator

查看
https://ceph.demo.com:8443/
在这里插入图片描述
在这里插入图片描述
当ceph集群配置完成后,可以通过dashboard看到详细信息。

4.5 存储osd配置

4.5.1 ceph.conf配置

ceph.conf添加如下信息

[client.bootstrap-osd]
# mon host = 10.2.20.90
keyring = /var/lib/ceph/bootstrap-osd/ceph.keyring

更新配置ceph.conf到各节点

# ansible ceph -m copy -a "src=ceph.conf dest=/etc/ceph/"

将bootstrap-osd key复制到各节点

ansible ceph -m copy -a "src=ceph.keyring dest=/var/lib/ceph/bootstrap-osd/"
ansible ceph -m shell -a "chown ceph:ceph -R /var/lib/ceph/bootstrap-osd"

4.5.2 添加ceph卷

在osd节点上操作,以ceph-node1为例。每个osd节点相同操作。
查看节点上的祼硬盘情况

# lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    0    8G  0 disk 
├─sda1        8:1    0  600M  0 part /boot/efi
├─sda2        8:2    0    1G  0 part /boot
└─sda3        8:3    0  6.4G  0 part ├─cl-root 253:0    0  5.6G  0 lvm  /└─cl-swap 253:1    0  820M  0 lvm  [SWAP]
sdb           8:16   0   10G  0 disk 
sdc           8:32   0   10G  0 disk 
sr0          11:0    1 1024M  0 rom  

将/dev/sdb和/dev/sdc挂入ceph,创建ceph卷,每一个osd都有独立的id.

# ceph-volume lvm create --data /dev/sdb
...
Running command: /usr/bin/systemctl enable --runtime ceph-osd@0stderr: Created symlink /run/systemd/system/ceph-osd.target.wants/ceph-osd@0.service → /usr/lib/systemd/system/ceph-osd@.service.
Running command: /usr/bin/systemctl start ceph-osd@0
--> ceph-volume lvm activate successful for osd ID: 0
--> ceph-volume lvm create successful for: /dev/sdb# ceph-volume lvm create --data /dev/sdc
Running command: /usr/bin/systemctl enable --runtime ceph-osd@1stderr: Created symlink /run/systemd/system/ceph-osd.target.wants/ceph-osd@1.service → /usr/lib/systemd/system/ceph-osd@.service.
Running command: /usr/bin/systemctl start ceph-osd@1
--> ceph-volume lvm activate successful for osd ID: 1
--> ceph-volume lvm create successful for: /dev/sdc

启动服务,每一个osd都有独立的id,启动osd服务时需指定osd id。

# systemctl enable ceph-osd@0
# systemctl enable ceph-osd@1
# systemctl start ceph-osd.target# ps -ef | grep osd
ceph        3492       1  0 10:38 ?        00:00:01 /usr/bin/ceph-osd -f --cluster ceph --id 0 --setuser ceph --setgroup ceph
ceph        4993       1  1 10:39 ?        00:00:01 /usr/bin/ceph-osd -f --cluster ceph --id 1 --setuser ceph --setgroup ceph

其它两个osd节点做相同操作,完成后可查看osd状态。

# ceph osd status
ID  HOST         USED  AVAIL  WR OPS  WR DATA  RD OPS  RD DATA  STATE      0  ceph-node1  20.6M  9.97G      0        0       0        0   exists,up  1  ceph-node1  20.6M  9.97G      0        0       0        0   exists,up  2  ceph-node2  21.0M  9.97G      0        0       0        0   exists,up  3  ceph-node2  20.3M  9.97G      0        0       0        0   exists,up  4  ceph-node3  19.7M  9.97G      0        0       0        0   exists,up  5  ceph-node3  20.2M  9.97G      0        0       0        0   exists,up  # ceph osd df
ID  CLASS  WEIGHT   REWEIGHT  SIZE    RAW USE  DATA     OMAP  META     AVAIL   %USE  VAR   PGS  STATUS0    hdd  0.00980   1.00000  10 GiB   21 MiB  496 KiB   0 B   21 MiB  10 GiB  0.21  1.01   16      up1    hdd  0.00980   1.00000  10 GiB   21 MiB  500 KiB   0 B   21 MiB  10 GiB  0.21  1.02   24      up2    hdd  0.00980   1.00000  10 GiB   22 MiB  920 KiB   0 B   21 MiB  10 GiB  0.21  1.02   22      up3    hdd  0.00980   1.00000  10 GiB   21 MiB  928 KiB   0 B   20 MiB  10 GiB  0.20  0.99   24      up4    hdd  0.00980   1.00000  10 GiB   20 MiB  500 KiB   0 B   20 MiB  10 GiB  0.20  0.97   18      up5    hdd  0.00980   1.00000  10 GiB   21 MiB  908 KiB   0 B   20 MiB  10 GiB  0.20  0.98   19      upTOTAL  60 GiB  127 MiB  4.2 MiB   0 B  122 MiB  60 GiB  0.21                   
MIN/MAX VAR: 0.97/1.02  STDDEV: 0.00# ceph -scluster:id:     9b7095ab-5193-420c-b2fb-2d343c57ef52health: HEALTH_OKservices:mon: 1 daemons, quorum mon1 (age 103m)mgr: mgr1(active, since 77m)osd: 6 osds: 6 up (since 74s), 6 in (since 106s)data:pools:   1 pools, 1 pgsobjects: 2 objects, 449 KiBusage:   123 MiB used, 60 GiB / 60 GiB availpgs:     1 active+clean# ceph osd pool ls
.mgr

4.6 mds进程配置

一个 Ceph 文件系统需要至少两个 RADOS 存储池,一个用于数据、一个用于元数据。
在生产中,配置这些存储池时需考虑:
1。为元数据存储池设置较高的副本水平,因为此存储池丢失任何数据都会导致整个文件系统失效。
2。为元数据存储池分配低延时存储器(像 SSD ),因为它会直接影响到客户端的操作延时。

将mds配置在ceph-mon1节点,在多个节点上可以配置多个mds服务。

4.6.1 配置mds服务

创建mds数据目录。

sudo -u ceph mkdir -p /var/lib/ceph/mds/ceph-mon1

创建keyring,并配置权限。

ceph-authtool --create-keyring /var/lib/ceph/mds/ceph-mon1/keyring --gen-key -n mds.mon1
ceph auth add mds.mon1 osd "allow rwx" mds "allow" mon "allow profile mds" -i /var/lib/ceph/mds/ceph-mon1/keyring
chown ceph:ceph -R /var/lib/ceph/mds/ceph-mon1

ceph.conf添加如下信息

[mds.mon1]
host = ceph-mon1
#mon host = 10.2.20.90
keyring = /var/lib/ceph/mds/ceph-mon1/keyring

更新配置ceph.conf到各节点

ansible ceph -m copy -a "src=ceph.conf dest=/etc/ceph/"

运行服务

# systemctl enable ceph-mds@mon1
# systemctl start ceph-mds.target

查看ceph状态

# ps -ef | grep mds
ceph        3617       1  1 11:16 ?        00:00:00 /usr/bin/ceph-mds -f --cluster ceph --id mon1 --setuser ceph --setgroup ceph
# ceph -scluster:id:     9b7095ab-5193-420c-b2fb-2d343c57ef52health: HEALTH_OKservices:mon: 1 daemons, quorum mon1 (age 2h)mgr: mgr1(active, since 2h)osd: 6 osds: 6 up (since 49m), 6 in (since 49m)data:pools:   1 pools, 1 pgsobjects: 2 objects, 449 KiBusage:   123 MiB used, 60 GiB / 60 GiB availpgs:     1 active+clean
# ceph mds stat1 up:standby

4.6.2 创建fs卷

1。一个cephfs最多占用2个mds进程,一主一副。
2。若有多个cephfs,需配置多个mds进程。
3。一个mds服务进程只负责一个fs卷。
4。当需要多个fs卷,可采用子卷方式。

ceph osd pool create guo-metadata 8
ceph osd pool create guo-data 8
ceph fs new guo-fs guo-metadata guo-data

查看fs卷

# ceph fs ls
name: guo-fs, metadata pool: guo-metadata, data pools: [guo-data ]# ceph mds stat
guo-fs:1 {0=mon1=up:active}# ceph -scluster:id:     9b7095ab-5193-420c-b2fb-2d343c57ef52health: HEALTH_OKservices:mon: 1 daemons, quorum mon1 (age 2h)mgr: mgr1(active, since 2h)mds: 1/1 daemons uposd: 6 osds: 6 up (since 57m), 6 in (since 57m)data:volumes: 1/1 healthypools:   3 pools, 41 pgsobjects: 24 objects, 451 KiBusage:   126 MiB used, 60 GiB / 60 GiB availpgs:     41 active+clean# ceph fs volume ls
[{"name": "guo-fs"}
]# ceph fs status guo-fs
guo-fs - 0 clients
======
RANK  STATE   MDS      ACTIVITY     DNS    INOS   DIRS   CAPS  0    active  mon1  Reqs:    0 /s    10     13     12      0   POOL        TYPE     USED  AVAIL  
guo-metadata  metadata  96.0k  18.9G  guo-data      data       0   18.9G  
MDS version: ceph version 17.2.6 (d7ff0d10654d2280e08f1ab989c7cdf3064446a5) quincy (stable)# ceph fs get guo-fs
Filesystem 'guo-fs' (1)
fs_name guo-fs
epoch   4
flags   12 joinable allow_snaps allow_multimds_snaps
created 2023-06-04T11:46:12.324425+0800
modified        2023-06-04T11:46:13.614449+0800
tableserver     0
root    0
session_timeout 60
session_autoclose       300
max_file_size   1099511627776
required_client_features        {}
last_failure    0
last_failure_osd_epoch  0
compat  compat={},rocompat={},incompat={1=base v0.20,2=client writeable ranges,3=default file layouts on dirs,4=dir inode in separate object,5=mds uses versioned encoding,6=dirfrag is stored in omap,7=mds uses inline data,8=no anchor table,9=file layout v2,10=snaprealm v2}
max_mds 1
in      0
up      {0=24251}
failed
damaged
stopped
data_pools      [3]
metadata_pool   2
inline_data     disabled
balancer
standby_count_wanted    0
[mds.mon1{0:24251} state up:active seq 454 addr [v2:10.2.20.90:6802/3326420411,v1:10.2.20.90:6803/3326420411] compat {c=[1],r=[1],i=[7ff]}]

查看fs使用情况

# ceph fs volume info  guo-fs
{"mon_addrs": ["10.2.20.90:6789"],"pools": {"data": [{"avail": 20347840512,"name": "guo-data","used": 0}],"metadata": [{"avail": 20347840512,"name": "guo-metadata","used": 98304}]}
}

4.6.3 cephfs mount测试

cephfs挂载的方式有多种,本文采用linux内核模块ceph方式,centos7.x或更高版本的内核默认安装ceph模块。
查验内核ceph模块

modinfo ceph

在管理机上操作

在cephfs卷上为使用创建子目录
# mount -t ceph -o mds_namespace=guo-fs,name=admin,secret=AQCwXntkCw+CGBAA/mdug0WT2jYDAFEN8tATOA== 10.2.20.90:6789:/ /root/cephfs
# mkdir -p /root/cephfs/{tp1,tp2}
# umount /root/cephfs创建cephfs访问用户
# ceph fs authorize guo-fs client.guofs /tp1 rw
[client.guofs]key = AQAmFnxkwo4WAxAAPpMEpIOfTvgc6jAQBKlf8A==查看
# ceph auth get client.guofs删除
# ceph auth rm client.guofs

在用户机上操作

# mount -t ceph -o mds_namespace=guo-fs,name=guofs,secret=AQAmFnxkwo4WAxAAPpMEpIOfTvgc6jAQBKlf8A== 10.2.20.90:6789:/tp1 /root/tp1
# df -Th | grep tp1
10.2.20.90:6789:/tp1 ceph       19G     0   19G   0% /root/tp1

4.7 rbd块存储配置

rbd块存储不需要特别的服务进程,通过mon进程可直接访问。

4.7.1 创建块设备

创建rbd设备使用的存储池

# ceph osd pool create rbd01_pool 64 64
# ceph osd pool application enable rbd01_pool rbd
# rbd pool init rbd01_pool
# ceph osd pool application get rbd01_pool
# ceph osd pool get rbd01_pool all

创建rbd类的pool的命名空间
rbd类pool的命名空间的作用:
在pool存储池上划分多个逻辑区域,不同区域间的用户是隔离的,相同区域的多个用户是可以访问对方资源的。
rbd类pool默认没有命名空间。

# rbd namespace create rbd01_pool/ns1
# rbd namespace create rbd01_pool/ns2
# rbd namespace ls rbd01_pool
NAME
ns1 
ns2

建立块设备对像

rbd create --size 1024 --image-feature layering rbd01_pool/ns1/disk11
rbd create --size 1024 --image-feature layering rbd01_pool/ns1/disk21
rbd create --size 1024 --image-feature layering rbd01_pool/ns2/disk11
rbd create --size 1024 --image-feature layering rbd01_pool/ns2/disk21

查看块对像

# rbd list  rbd01_pool/ns1  --long
NAME    SIZE   PARENT  FMT  PROT  LOCK
disk11  1 GiB            2            
disk21  1 GiB            2 # rbd list  rbd01_pool/ns2  --long
NAME    SIZE   PARENT  FMT  PROT  LOCK
disk11  1 GiB            2            
disk21  1 GiB            2  # rbd info rbd01_pool/ns1/disk11
rbd image 'disk11':size 1 GiB in 256 objectsorder 22 (4 MiB objects)snapshot_count: 0id: 5f57d0156264block_name_prefix: rbd_data.5f57d0156264format: 2features: layeringop_features: flags: create_timestamp: Sun Jun  4 12:58:54 2023access_timestamp: Sun Jun  4 12:58:54 2023modify_timestamp: Sun Jun  4 12:58:54 2023

创建rbd设备用户

# ceph auth get-or-create client.user01 mon 'profile rbd' osd 'profile rbd pool=rbd01_pool namespace=ns1'
# ceph auth get client.user01
[client.user01]key = AQAGL3xkXzJ8GxAAOOj9RmDe5jb96koJTYEpwA==caps mon = "profile rbd"caps osd = "profile rbd pool=rbd01_pool namespace=ns1"

4.7.2 用户使用块设备

在用户主机上操作.

低版本的ceph-common中的rbd命令不支持pool的命名空间配置,需采用高版本的ceph-common来安装rbd.

# yum -y install ceph-common

认证配置

# mkdir /etc/ceph   # cat > /etc/ceph/ceph.conf << 'EOF'
[global]
mon_host = 10.2.20.90:6789
EOF# cat > /etc/ceph/ceph.client.user01.keyring << 'EOF'
[client.user01]key = AQAGL3xkXzJ8GxAAOOj9RmDe5jb96koJTYEpwA==
EOF

查看rbc设备

# rbd -n client.user01  -m 10.2.20.90 -k /etc/ceph/ceph.client.user01.keyring  ls rbd01_pool/ns1
disk11
disk21# rbd -n client.user01  ls rbd01_pool/ns1
disk11
disk21

针对块设备执行写入性能测试

# rbd bench --io-type write rbd01_pool/ns1/disk11 -n client.user01
bench  type write io_size 4096 io_threads 16 bytes 1073741824 pattern sequentialSEC       OPS   OPS/SEC   BYTES/SEC1      6208   6066.31    24 MiB/s2      6672   3192.38    12 MiB/s3      6928   2173.41   8.5 MiB/s4      9712   2317.31   9.1 MiB/s5     11840   2363.65   9.2 MiB/s6     14832   1730.69   6.8 MiB/s

挂载块存储

# rbd map rbd01_pool/ns1/disk11 -n client.user01
/dev/rbd0

查看已映射块设备

# rbd showmapped
id  pool        namespace  image   snap  device   
0   rbd01_pool  ns1        disk11  -     /dev/rbd0

格式化

# mkfs.xfs /dev/rbd0
# mkdir /tp2
# mount /dev/rbd0 /tp2
# df -h
...
/dev/rbd0           1014M   40M  975M   4% /tp2

取消块设备映射

rbd unmap rbd01_pool/ns1/disk11

4.8 rgw配置

4.8.1 存储池配置

对像存储池配置

ceph osd pool create .rgw.root 16 16 replicated
ceph osd pool create zone-test.rgw.control 16 16 replicated
ceph osd pool create zone-test.rgw.meta 16 16 replicated
ceph osd pool create zone-test.rgw.log 16 16 replicated
ceph osd pool create zone-test.rgw.buckets.index 16 16 replicated
ceph osd pool create zone-test.rgw.buckets.data 16 16 replicated
ceph osd pool create zone-test.rgw.buckets.non-ect 16 16 replicatedceph osd pool application enable  .rgw.root rgw
ceph osd pool application enable  zone-test.rgw.control rgw
ceph osd pool application enable  zone-test.rgw.meta rgw
ceph osd pool application enable  zone-test.rgw.log rgw
ceph osd pool application enable  zone-test.rgw.buckets.index rgw
ceph osd pool application enable  zone-test.rgw.buckets.data rgw
ceph osd pool application enable  zone-test.rgw.buckets.non-ect rgw

realm配置

radosgw-admin realm create --rgw-realm=realm-test --default

zonegroup配置

radosgw-admin zonegroup create --rgw-zonegroup=zonegroup-test --endpoints=10.2.20.90:80 --default --master

zone配置

radosgw-admin zone create --rgw-zone=zone-test --rgw-zonegroup=zonegroup-test  --endpoints=10.2.20.90:80 --default --master

period更新

radosgw-admin period update --commit

4.8.2 rgw进程配置

在ceph-mon1节点上面操作

4.8.2.1 keyring配置

配置实例名称变量
# instance_name=rgw1新增keyring存放目录
# mkdir -p /var/lib/ceph/radosgw/ceph-radosgw.${instance_name}创建rgw服务需要的keyring
# ceph auth get-or-create client.radosgw.${instance_name} osd 'allow rwx' mon 'allow rw' -o /var/lib/ceph/radosgw/ceph-radosgw.${instance_name}/keyring配置权限
# chown -R ceph:ceph /var/lib/ceph/radosgw查看cephx
# ceph auth get client.radosgw.${instance_name}
[client.radosgw.rgw1]key = AQAwQ3xkHy6/EBAAKQlW/7WXpt7HyxiOdcIv8w==caps mon = "allow rw"caps osd = "allow rwx"

4.8.2.2 rgw服务配置

ceph.conf添加如下信息

[client.radosgw.rgw1]
host = ceph-mon1
rgw_frontends = "beast port=80"
rgw_enable_usage_log = true
keyring = /var/lib/ceph/radosgw/ceph-radosgw.rgw1/keyring
rgw_realm = "realm-test"
rgw_zonegroup = "zonegroup-test"
rgw_zone = "zone-test"
rgw_verify_ssl = false

更新配置ceph.conf到各节点

ansible ceph -m copy -a "src=ceph.conf dest=/etc/ceph/"

安装rgw服务

yum -y install ceph-radosgw

启动服务

# systemctl enable ceph-radosgw@radosgw.${instance_name}
# systemctl start ceph-radosgw.target

查看进程

# ps -ef | grep radosgw
ceph       12853       1  5 00:32 ?        00:00:00 /usr/bin/radosgw -f --cluster ceph --name client.radosgw.sr1 --setuser ceph --setgroup ceph

4.8.3 rgw测试

在管理机上建立rgw用户

# radosgw-admin user create --uid="guofs" --display-name="test"
# radosgw-admin user info --uid="guofs" | grep access_key -A1"access_key": "LLOGCYL0FAVR2K4YFZB8","secret_key": "FbkyDqNGumDob5n54NRMtaYskvrVQgRrddHRivcS"

在用户主机上配置.
测试工具
https://github.com/peak/s5cmd

外部主机上操作如下

export AWS_ENDPOINT=10.2.20.90:80
export AWS_ACCESS_KEY_ID=LLOGCYL0FAVR2K4YFZB8
export AWS_SECRET_ACCESS_KEY=FbkyDqNGumDob5n54NRMtaYskvrVQgRrddHRivcS

在上传文件前,需先建立存储桶。

# s5cmd --endpoint-url http://$AWS_ENDPOINT mb s3://test01
# s5cmd --endpoint-url http://$AWS_ENDPOINT mb s3://test02

查看存储桶

# s5cmd --endpoint-url http://$AWS_ENDPOINT ls
2023/06/04 10:36:59  s3://test01
2023/06/04 10:37:08  s3://test02

上传

# echo "hello rgw" > /tmp/test.txt
# s5cmd --endpoint-url http://$AWS_ENDPOINT cp /tmp/test.txt s3://test01

查看文件列表

# s5cmd --endpoint-url http://$AWS_ENDPOINT ls s3://test01
2023/06/04 10:37:44                10 test.txt

下载

# s5cmd --endpoint-url http://$AWS_ENDPOINT cp s3://test01/test.txt ./
cp s3://test01/test.txt test.txt
# ll
total 4
-rw-r--r-- 1 root root 10 Jun  4 18:45 test.txt

五、计算层/k8s/istio

节点说明

节点os配置ip角色
mgmRocky9.12vCPU,RAM4GB,HD:8GB10.2.20.59/192.168.3.x管理节点,ssh免密
k8s-master1Rocky9.14vCPU,RAM4GB,HD:32GB10.2.20.110/192.168.3.x主控
k8s-node1Rocky9.14vCPU,RAM4GB,HD:32GB10.2.20.111/192.168.3.xworker
k8s-node2Rocky9.14vCPU,RAM4GB,HD:32GB10.2.20.112/192.168.3.xworker

K8S版本:v1.27.2

5.1 K8S节点配置

5.1.1 基础配置

k8s所有节点配置此部分

5.1.1.1 基础包和内核参数

配置hosts文件

cat >> /etc/hosts << 'EOF'
10.2.20.110     k8s-master1
10.2.20.111     k8s-node1
10.2.20.112     k8s-node2
EOF

基础配置及软件包

swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
free -m
systemctl stop firewalld && systemctl disable firewalld
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
ip_tables
iptable_filter
overlay
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
yum -y install epel-release
yum -y install bash-completion net-tools gcc wget curl telnet tree lrzsz iproute zip

5.1.1.2 容器运行时配置

容器运行时有docker和cri-o两种常用。
本文采用cri-o
https://github.com/cri-o/cri-o/

安装cri-o

yum -y install curl jq tar
curl https://raw.githubusercontent.com/cri-o/cri-o/main/scripts/get | bash -s -- -a amd64
systemctl enable --now crio.service
systemctl start crio

配置cri-o

# cat /etc/crictl.yaml
runtime-endpoint: unix:///var/run/crio/crio.sock
image-endpoint: unix:///var/run/crio/crio.sock
timeout: 10
debug: false# vi /etc/crio/crio.conf
[crio.image]
pause_image = "registry.aliyuncs.com/google_containers/pause:3.9"# systemctl restart crio

测试

# crictl --runtime-endpoint unix:///run/crio/crio.sock version
Version:  0.1.0
RuntimeName:  cri-o
RuntimeVersion:  1.27.0
RuntimeApiVersion:  v1# crio --version
crio version 1.27.0
Version:        1.27.0
GitCommit:      844b43be4337b72a54b53518667451c975515d0b
GitCommitDate:  2023-06-03T07:36:19Z
GitTreeState:   dirty
BuildDate:      1980-01-01T00:00:00Z
GoVersion:      go1.20.4
Compiler:       gc
Platform:       linux/amd64
Linkmode:       static
BuildTags:      staticnetgoosusergoexclude_graphdriver_btrfsexclude_graphdriver_devicemapperseccompapparmorselinux
LDFlags:          unknown
SeccompEnabled:   true
AppArmorEnabled:  false

5.1.1.3 kubectl kubelet kubeadm安装

配置阿里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

版本查看

# yum -y makecache
# yum list kubelet --showduplicates | sort -r
...
kubelet.x86_64                       1.27.2-0                        kubernetes 
kubelet.x86_64                       1.27.2-0                        @kubernetes
kubelet.x86_64                       1.27.1-0                        kubernetes 
kubelet.x86_64                       1.27.0-0                        kubernetes 
...

安装kubectl kubelet kubeadm ,默认安装最新版

# yum -y install kubectl kubelet kubeadm

提示:
在各节点安装k8s成功后再“systemctl enable kubelet”

5.1.1.4 k8s系统镜像准备

在配置master和worker节点时,会从公网拉取k8s系统镜像。
可将这些镜像提前pull到节点本地。
查看k8s系统镜像列表

# kubeadm config images list --kubernetes-version=1.27.2  --image-repository="registry.aliyuncs.com/google_containers" 
W0604 23:32:32.215609   11292 images.go:80] could not find officially supported version of etcd for Kubernetes v1.27.2, falling back to the nearest etcd version (3.5.7-0)
registry.aliyuncs.com/google_containers/kube-apiserver:v1.27.2
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.27.2
registry.aliyuncs.com/google_containers/kube-scheduler:v1.27.2
registry.aliyuncs.com/google_containers/kube-proxy:v1.27.2
registry.aliyuncs.com/google_containers/pause:3.9
registry.aliyuncs.com/google_containers/etcd:3.5.7-0
registry.aliyuncs.com/google_containers/coredns:v1.10.1

pull镜像

kubeadm config images pull --kubernetes-version=1.27.2 --image-repository="registry.aliyuncs.com/google_containers"

查看

# crictl images
IMAGE                                                             TAG                 IMAGE ID            SIZE
registry.aliyuncs.com/google_containers/coredns                   v1.10.1             ead0a4a53df89       53.6MB
registry.aliyuncs.com/google_containers/etcd                      3.5.7-0             86b6af7dd652c       297MB
registry.aliyuncs.com/google_containers/kube-apiserver            v1.27.2             c5b13e4f7806d       122MB
registry.aliyuncs.com/google_containers/kube-controller-manager   v1.27.2             ac2b7465ebba9       114MB
registry.aliyuncs.com/google_containers/kube-proxy                v1.27.2             b8aa50768fd67       72.7MB
registry.aliyuncs.com/google_containers/kube-scheduler            v1.27.2             89e70da428d29       59.8MB
registry.aliyuncs.com/google_containers/pause                     3.9                 e6f1816883972       750kB

5.1.2 master节点配置

安装第一台master节点

# kubeadm init \
--kubernetes-version="1.27.2" \
--cri-socket="/var/run/crio/crio.sock" \
--control-plane-endpoint="10.2.20.110" \
--apiserver-advertise-address=10.2.20.110 \
--image-repository="registry.aliyuncs.com/google_containers" \
--service-cidr=10.10.0.0/16 \
--pod-network-cidr="10.244.0.0/16" \
--ignore-preflight-errors=Swap \
--upload-certs
输出
...
[addons] Applied essential addon: kube-proxyYour Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user:mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configAlternatively, if you are the root user, you can run:export KUBECONFIG=/etc/kubernetes/admin.confYou 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:
第二台master安装kubeadm join 10.2.20.110:6443 --token y1dzd6.rmojednvdy1ukevo \--discovery-token-ca-cert-hash sha256:4fc878964ab80032ee47e17cdf8a67700f1cc58a72af69d7ffa3b7e0ac0b2b09 \--control-plane --certificate-key 45d54477eeb7228c6728cbc343c1bb59cce539f3f65e83e6136a724a43b45ac9Please 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:
worker节点安装
kubeadm join 10.2.20.110:6443 --token y1dzd6.rmojednvdy1ukevo \--discovery-token-ca-cert-hash sha256:4fc878964ab80032ee47e17cdf8a67700f1cc58a72af69d7ffa3b7e0ac0b2b09 

配置kubelet开机引导

systemctl enable kubelet.service

配置kubectl

创建kubectl环境变量
# mkdir -p $HOME/.kube
# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# sudo chown $(id -u):$(id -g) $HOME/.kube/config
# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
# source /etc/profile
执行下面命令,使kubectl可以自动补充
# echo "source <(kubectl completion bash)" >> ~/.bash_profile
# source .bash_profile

测试

# kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.27.2
Kustomize Version: v5.0.1
Server Version: v1.27.2# kubectl get node
NAME          STATUS   ROLES           AGE     VERSION
k8s-master1   Ready    control-plane   8m45s   v1.27.2

5.1.3 worker节点配置

所有结节运行如下命令

# kubeadm join 10.2.20.110:6443 --token y1dzd6.rmojednvdy1ukevo \--discovery-token-ca-cert-hash sha256:4fc878964ab80032ee47e17cdf8a67700f1cc58a72af69d7ffa3b7e0ac0b2b09 
输出
...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

配置开机启动

systemctl enable kubelet.service

5.1.4 管理机mgm配置kubectl

在k8集群外安装k8s客户端命令kubectl.
创建kubectl环境变量

scp k8s-master1:/usr/bin/kubectl /usr/bin/
mkdir -p $HOME/.kube
scp k8s-master1:/etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
mkdir /etc/kubernetes
scp k8s-master1:/etc/kubernetes/admin.conf /etc/kubernetes/
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
source /etc/profile

kubectl可以自动补充

echo "source <(kubectl completion bash)" >> ~/.bash_profile
source .bash_profile

测试

# 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","reason":""}   # kubectl get node
NAME          STATUS   ROLES           AGE   VERSION
k8s-master1   Ready    control-plane   33m   v1.27.2
k8s-node1     Ready    <none>          20m   v1.27.2
k8s-node2     Ready    <none>          19m   v1.27.2# kubectl get pod -A
NAMESPACE     NAME                                  READY   STATUS    RESTARTS   AGE
kube-system   coredns-7bdc4cb885-hcl6t              1/1     Running   0          16m
kube-system   coredns-7bdc4cb885-hvmgs              1/1     Running   0          16m
kube-system   etcd-k8s-master1                      1/1     Running   0          17m
kube-system   kube-apiserver-k8s-master1            1/1     Running   0          16m
kube-system   kube-controller-manager-k8s-master1   1/1     Running   0          16m
kube-system   kube-proxy-464dg                      1/1     Running   0          16m
kube-system   kube-proxy-7vtxg                      1/1     Running   0          2m53s
kube-system   kube-proxy-crfkg                      1/1     Running   0          3m52s
kube-system   kube-scheduler-k8s-master1            1/1     Running   0          16m

5.1.5 访问私有仓库harbor配置

在管理机上操作。
k8s各节点安装成功后再配置此项

5.1.5.1 k8s/crictl访问私有仓库配置

私有CA根证书添加到k8s所有节点的根证书链中

ansible k8s -m shell -a "wget http://10.2.20.59/ssl/ca.pem -O /tmp/ca.pem"
ansible k8s -m shell -a "cat /tmp/ca.pem >> /etc/pki/tls/certs/ca-bundle.crt"

创建config.json用于存储私仓用户和密码。

# cat > config.json << 'EOF'
{"auths": {"harbor.demo.com": {"auth": "YWRtaW46MTIzNDU2NzgK"}}
}
EOF
# ansible k8s -m copy -a "src=config.json dest=/var/lib/kubelet/"
# ansible k8s -m shell -a "systemctl restart kubelet.service"

配置cri-o/crictl使用config.json

# vi crio.conf
...
[crio.image]
global_auth_file = "/var/lib/kubelet/config.json"# ansible k8s -m copy -a "src=crio.conf dest=/etc/crio/"
# ansible k8s -m shell -a "systemctl restart crio"

提示:
上述办法是将私仓的帐号存储在config.json,供所有命空间使用。

5.1.5.2 测试

crictl拉取镜像(在k8s某节点上测试)

# crictl pull harbor.demo.com/web/busybox:v2.1
Image is up to date for harbor.demo.com/web/busybox@sha256:0152995fd9b720acfc49ab88e48bc9f4509974fb17025896740ae02396e37388

k8s从私仓拉取镜像

# kubectl create namespace test# cat app-c19-1.yaml
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testreplicas: 1template:metadata:name: app-testnamespace: testlabels:app: app-testspec:containers:- name: httpimage: harbor.demo.com/test/centos:v0.1.1imagePullPolicy: IfNotPresentports:- name: port-test-01containerPort: 8080protocol: TCP# kubectl -n test get all
NAME                            READY   STATUS    RESTARTS   AGE
pod/app-test-55f5b45c96-7fg8g   1/1     Running   0          17sNAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/app-test   1/1     1            1           17sNAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/app-test-55f5b45c96   1         1         1       17s

5.1.5.3 secrets存储私仓帐号

"5.1.5.1"是将私仓的帐号存储在config.json,供所有命空间使用。
也可以使用secrets存储私仓的帐号。

# kubectl create secret docker-registry harbor-test \--docker-server="harbor.demo.com" \--docker-username="admin" \--docker-password="12qwaszx+pp"# cat app-c19-2.yaml
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testreplicas: 1template:metadata:name: app-testnamespace: testlabels:app: app-testspec:imagePullSecrets:- name: harbor-testcontainers:- name: httpimage: harbor.demo.com/test/centos:v0.1.2imagePullPolicy: IfNotPresentports:- name: port-test-01containerPort: 8080protocol: TCP# kubectl apply -f app-c19-2.yaml# kubectl -n test get pod
NAME                       READY   STATUS    RESTARTS   AGE
app-test-6644fb79b-g4njz   1/1     Running   0          18s

采有imagePullSecrets指定私仓secrets.

5.2 网络配置calico

Kubernetes通过CNI协议支持多种网络模型,如Calico、Flannel、Open vSwitch、Weave、Cilium等。

本文以calico为例。

5.2.1 Calico安装

https://github.com/projectcalico/cni-plugin
https://github.com/projectcalico/calico
https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart

本文采用Calico插件,是一个纯三层的方案,不需要 Overlay,基于 Iptables 增加了策略配置。

Calico特点

安装

# wget https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/calico.yaml
# cat calico.yaml | grep "image:"image: docker.io/calico/cni:v3.26.0image: docker.io/calico/cni:v3.26.0image: docker.io/calico/node:v3.26.0image: docker.io/calico/node:v3.26.0image: docker.io/calico/kube-controllers:v3.26.0
这镜像转存到私仓,并修改calico.yaml中的镜像地址,将docker.io改为harbor.demo.com
# cat calico.yaml | grep "image: "image: harbor.demo.com/calico/cni:v3.26.0image: harbor.demo.com/calico/cni:v3.26.0image: harbor.demo.com/calico/node:v3.26.0image: harbor.demo.com/calico/node:v3.26.0image: harbor.demo.com/calico/kube-controllers:v3.26.0
安装
# kubectl apply -f  calico.yaml

查看

# kubectl get pod --all-namespaces
NAMESPACE     NAME                                      READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-868d576d4-7jrwh   1/1     Running   0          12m
kube-system   calico-node-ld8gv                         1/1     Running   0          17m
kube-system   calico-node-s5x7q                         1/1     Running   0          17m
kube-system   calico-node-zfr76                         1/1     Running   0          17m
kube-system   coredns-7bdc4cb885-hcl6t                  1/1     Running   0          4h20m
kube-system   coredns-7bdc4cb885-hvmgs                  1/1     Running   0          4h20m
kube-system   etcd-k8s-master1                          1/1     Running   0          4h20m
kube-system   kube-apiserver-k8s-master1                1/1     Running   0          4h20m
kube-system   kube-controller-manager-k8s-master1       1/1     Running   0          4h20m
kube-system   kube-proxy-464dg                          1/1     Running   0          4h20m
kube-system   kube-proxy-7vtxg                          1/1     Running   0          4h6m
kube-system   kube-proxy-crfkg                          1/1     Running   0          4h7m
kube-system   kube-scheduler-k8s-master1                1/1     Running   0          4h20m

配置cri-o采用cni插件

# tree /etc/cni/net.d/
/etc/cni/net.d/
├── 10-calico.conflist
├── 11-crio-ipv4-bridge.conflist
└── calico-kubeconfig# tree /opt/cni/bin/
/opt/cni/bin/
├── bandwidth
├── bridge
├── calico
├── calico-ipam
├── dhcp
├── dummy
├── firewall
├── flannel
├── host-device
├── host-local
├── install
├── ipvlan
├── loopback
├── macvlan
├── portmap
├── ptp
├── sbr
├── static
├── tap
├── tuning
├── vlan
└── vrf可修改cri-o配置来识别calico网络
# vi /etc/crio/crio.conf
[crio.network]# The default CNI network name to be selected. If not set or "", then
# CRI-O will pick-up the first one found in network_dir.
# cni_default_network = ""# Path to the directory where CNI configuration files are located.
network_dir = "/etc/cni/net.d/"# Paths to directories where CNI plugin binaries are located.
plugin_dirs = ["/opt/cni/bin/",
]# ansible k8s -m copy -a "src=crio.conf dest=/etc/crio/"
# ansible k8s -m shell -a "systemctl restart crio"

5.2.2 Calicoctl工具

calicoctl 是 Calico 客户端管理工具。 可以方便的管理 calico 网络,配置和安全策略,calicoctl 命令行提供了许多资源管理命令,允许您创建,修改,删除和查看不同的 Calico 资源,网络资源包含:node,bgpPeer,hostEndpoint,workloadEndpoint,ipPool,policy,profile等。

提示
1。calico版本与calicoctl版本要相同
2。在master节点安装此命令

安装

# curl -L https://github.com/projectcalico/calico/releases/latest/download/calicoctl-linux-amd64 -o calicoctl
# mv calicoctl /sbin/
# chmod +x /sbin/calicoctl# calicoctl version
Client Version:    v3.26.0
Git commit:        8b103f46f
Cluster Version:   v3.25.1
Cluster Type:      k8s,bgp,kubeadm,kdd# mkdir /etc/calico# vi /etc/calico/calicoctl.cfg 
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:datastoreType: "kubernetes"kubeconfig: "/root/.kube/config"# calicoctl node status
Calico process is running.IPv4 BGP status
+--------------+-------------------+-------+----------+-------------+
| PEER ADDRESS |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+--------------+-------------------+-------+----------+-------------+
| 192.168.3.13 | node-to-node mesh | up    | 08:19:18 | Established |
| 192.168.3.8  | node-to-node mesh | up    | 08:19:09 | Established |
+--------------+-------------------+-------+----------+-------------+IPv6 BGP status
No IPv6 peers found.

5.3 metrics-server配置

https://github.com/kubernetes-sigs/metrics-server
https://github.com/kubernetes-sigs/metrics-server/releases

Metrics Server 是 Kubernetes 内置自动缩放管道的可扩展、高效的容器资源指标来源,K8S 资源指标监控,如pod的内存或cpu使用情况。

Metrics Server 从 Kubelets 收集资源指标,并通过Metrics API在 Kubernetes apiserver 中公开它们,以供 HPA(Horizo​​ntal Pod Autoscaler,水平自动缩放)
和VPA(Vertical Pod Autoscaler,垂直自动缩放)使用。Metrics API 也可以通过 访问kubectl top,从而更容易调试自动缩放管道。

kube-apiserver 必须启用聚合层,即在/etc/kubernetes/manifests/kube-apiserver.yaml添加“enable-aggregator-routing=true”,如下:

# vi /etc/kubernetes/manifests/kube-apiserver.yaml
...
spec:containers:- command:- kube-apiserver- --advertise-address=10.2.20.110- --allow-privileged=true- --authorization-mode=Node,RBAC- --client-ca-file=/etc/kubernetes/pki/ca.crt- --enable-admission-plugins=NodeRestriction- --enable-bootstrap-token-auth=true- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key- --etcd-servers=https://127.0.0.1:2379- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key- --requestheader-allowed-names=front-proxy-client- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt- --requestheader-extra-headers-prefix=X-Remote-Extra-- --requestheader-group-headers=X-Remote-Group- --requestheader-username-headers=X-Remote-User- --secure-port=6443- --service-account-issuer=https://kubernetes.default.svc.cluster.local- --service-account-key-file=/etc/kubernetes/pki/sa.pub- --service-account-signing-key-file=/etc/kubernetes/pki/sa.key- --service-cluster-ip-range=10.10.0.0/16- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key- --enable-aggregator-routing=trueimage: registry.aliyuncs.com/google_containers/kube-apiserver:v1.27.2imagePullPolicy: IfNotPresent
...
# systemctl restart kubelet.service

安装

# wget github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.3/components.yaml添加kubelet-insecure-tls,如下:
# vi components.yaml 
...spec:containers:- args:- --cert-dir=/tmp- --secure-port=4443- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname- --kubelet-use-node-status-port- --metric-resolution=15s- --kubelet-insecure-tlsimage: harbor.demo.com/metrics-server/metrics-server:v0.6.3
...# kubectl apply -f components.yaml

测试

# kubectl top node
NAME              CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
c8-k8s-master01   242m         6%     1454Mi          40%       
c8-k8s-worker01   92m          2%     687Mi           18%       
c8-k8s-worker02   102m         2%     725Mi           19%   # kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes"
{"kind":"NodeMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{},"items":[{"metadata":{"name":"k8s-master1","creationTimestamp":"2023-06-05T08:10:10Z","labels":{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"k8s-master1","kubernetes.io/os":"linux","node-role.kubernetes.io/control-plane":"","node.kubernetes.io/exclude-from-external-load-balancers":""}},"timestamp":"2023-06-05T08:09:56Z","window":"20.059s","usage":{"cpu":"283196769n","memory":"1611636Ki"}},{"metadata":{"name":"k8s-node1","creationTimestamp":"2023-06-05T08:10:10Z","labels":{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"k8s-node1","kubernetes.io/os":"linux"}},"timestamp":"2023-06-05T08:09:54Z","window":"20.042s","usage":{"cpu":"104153377n","memory":"1059760Ki"}},{"metadata":{"name":"k8s-node2","creationTimestamp":"2023-06-05T08:10:10Z","labels":{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"k8s-node2","kubernetes.io/os":"linux"}},"timestamp":"2023-06-05T08:09:55Z","window":"20.042s","usage":{"cpu":"104032381n","memory":"976512Ki"}}]}    

5.4 metallb配置

https://github.com/google/metallb
https://metallb.universe.tf/installation/
https://metallb.universe.tf/configuration/

MetalLB 是一个负载均衡器,专门解决裸金属 Kubernetes 集群中无法使用 LoadBalancer 类型服务的痛点。MetalLB 使用标准化的路由协议,
以便裸金属 Kubernetes 集群上的外部服务也尽可能地工作。

在云厂商提供的 Kubernetes 集群中,Service 声明使用 LoadBalancer时,云平台会自动分配一个负载均衡器的IP地址给你,应用可以通过
这个地址来访问。

MetalLB 会在 Kubernetes 内运行,监控服务对象的变化,一旦监测到有新的 LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,
就会完成地址分配和外部声明两部分的工作。

网络宣告方式

1。Layer 2 模式
ayer 2 模式下,每个 Service 会有集群中的一个 Node 来负责。服务的入口流量全部经由单个节点,然后该节点的 Kube-Proxy 会把流量再转
发给服务的 Pods。也就是说,该模式下 MetalLB 并没有真正提供负载均衡器。尽管如此,MetalLB 提供了故障转移功能,如果持有 IP 的节点
出现故障,则默认 10 秒后即发生故障转移,IP 会被分配给其它健康的节点。

优点:
是它的通用性:它可以在任何以太网网络上运行,不需要特殊的硬件。

2。BGP 模式
BGP 模式下,集群中所有node都会跟上联路由器建立BGP连接,并且会告知路由器应该如何转发service的流量。

优点:
BGP模式下才是一个真正的 LoadBalancer,通过BGP协议正确分布流量,不再需要一个Leader节点。

5.4.1 安装

# wget https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml 
# cat metallb-native.yaml | grep image:image: quay.io/metallb/controller:v0.13.10image: quay.io/metallb/speaker:v0.13.10
将镜像转存在私有仓库
# cat metallb-native.yaml | grep image:image: harbor.demo.com/metallb/controller:v0.13.10image: harbor.demo.com/metallb/speaker:v0.13.10# kubectl apply -f ./metallb-native.yaml# kubectl get all -n metallb-system
NAME                              READY   STATUS    RESTARTS   AGE
pod/controller-746c786cf9-hdcvp   0/1     Running   0          17s
pod/speaker-224m6                 0/1     Running   0          17s
pod/speaker-cqhnr                 0/1     Running   0          17s
pod/speaker-s2fq6                 0/1     Running   0          17sNAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/webhook-service   ClusterIP   10.10.237.41   <none>        443/TCP   18sNAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/speaker   3         3         0       3            0           kubernetes.io/os=linux   18sNAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/controller   0/1     1            0           18sNAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/controller-746c786cf9   1         1         0       17s

5.4.2 配置LB网络

# cat metallb-cm.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:name: first-poolnamespace: metallb-system
spec:addresses:- 192.168.3.180-192.168.3.200---apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:name: examplenamespace: metallb-system
spec:ipAddressPools:- first-pool# kubectl apply -f  metallb-cm.yaml# kubectl get IPAddressPool,L2Advertisement -n metallb-system
NAME                                  AUTO ASSIGN   AVOID BUGGY IPS   ADDRESSES
ipaddresspool.metallb.io/first-pool   true          false             ["192.168.3.180-192.168.3.200"]NAME                                 IPADDRESSPOOLS   IPADDRESSPOOL SELECTORS   INTERFACES
l2advertisement.metallb.io/example   ["first-pool"]                         

5.4.3 测试

pod/svc样例,配置为:“type: LoadBalancer”

# cat app-c19-3.yaml
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testreplicas: 1template:metadata:name: app-testnamespace: testlabels:app: app-testspec:containers:- name: httpimage: harbor.demo.com/test/centos:v0.1.1imagePullPolicy: IfNotPresentports:- name: port-test-01containerPort: 8080protocol: TCP---apiVersion: v1
kind: Service
metadata:labels:app: app-testname: app-testnamespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: app-testports:- name: port01port: 7071targetPort: 8080protocol: TCPtype: LoadBalancer

应用及查看

# kubectl apply -f app-c19-3.yaml # kubectl -n test get svc
NAME       TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
app-test   LoadBalancer   10.10.39.255   192.168.3.180   7071:31874/TCP   95s

这样可以直接使用LB IP来访问

# curl -X POST http://192.168.3.180:7071/test
POST    Hello,world-v10
hello,method is post

5.5 Ingress配置

pod对外提供服务。主要有如下两种方式。

其一:pod直接对外方式

类型说明
hostNetwork:truepod直接使用物理节点的网络命名空间资源
hostPort: 8088pod仅使用物理节点的节点自身IP和某个端口

其二:svc方式(svc转发pod端口流量,原理是基于iptables和ipvs)

类型说明
ClusterIP情况一:svc只供svc所在网络内部访问
情况二:通过代理方式(如kubectl proxy、kube proxy)将svc服务代理出去
NodePort使用节点ip和端口将svc服务暴露出去
LoadBalancer此时需需metalLB支持
情况一:svc直接使用外部网络(非节点网络)将svc暴露出去
情况二:采用Ingress Controller,将svc服务代理出去.此时svc采用ClusterIP方式,而Ingress采用LB方式

其中Ingress Controller是主要方式。

5.5.1 Ingress Controller

Service他的工作原理是基于iptables和ipvs的,iptables和ipvs是四层代理的,Layer4层代理有个缺陷就是他只是工作在tcp/ip协议栈,而无法处理Layer7流量,基于此需求背景而产生Ingress。

Ingress 提供了负载均衡器的典型特性:HTTP 路由、粘性会话、SSL 终止、SSL直通、TCP 和 UDP 负载平衡等。

Ingress 只是一个统称,其由 Ingress 和 Ingress Controller 两部分组成,如下。

类型说明
ingress resourcesingress规则,这个就是一个类型为Ingress的k8s api对象
ingress controller核心是一个deployment,实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,其中service的类型用LoadBalancer方式

5.5.2 nginx ingress

参考
http://github.com/nginxinc/kubernetes-ingress
https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/
https://hub.docker.com/r/nginx/nginx-ingress
https://docs.nginx.com/nginx-ingress-controller
https://www.nginx.com/products/nginx-ingress-controller

这是 NGINX 公司开发的官方产品,它也有一个基于 NGINX Plus 的商业版。NGINX 的控制器具有很高的稳定性、持续的向后兼容性,且没有任何第三方模块。

5.5.2.1 安装

下载

# wget https://github.com/nginxinc/kubernetes-ingress/archive/refs/heads/main.zip
# unzip main.zip
# cd kubernetes-ingress-main/deployments

安装

kubectl apply -f common/ns-and-sa.yaml
kubectl apply -f rbac/rbac.yaml
kubectl apply -f common/nginx-config.yaml
kubectl apply -f common/ingress-class.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml
kubectl apply -f deployment/nginx-ingress.yaml
kubectl apply -f service/loadbalancer.yaml

查看

# kubectl get ingressclass
NAME    CONTROLLER                     PARAMETERS   AGE
nginx   nginx.org/ingress-controller   <none>       25s# kubectl get svc --namespace=nginx-ingress
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
nginx-ingress   LoadBalancer   10.10.122.65   192.168.3.180   80:31582/TCP,443:32381/TCP   23s# kubectl get pods --namespace=nginx-ingress
NAME                             READY   STATUS    RESTARTS   AGE
nginx-ingress-6f6b89c69b-nxgq4   1/1     Running   0          39s

5.5.2.2 测试

命名空间定义

kubectl create namespace test
kubectl config set-context kubernetes-admin@kubernetes --namespace='test'

创建pod/svc

# cat app-c24.yaml 
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testreplicas: 1template:metadata:name: app-testnamespace: testlabels:app: app-testspec:containers:- name: httpimage: harbor.demo.com/test/centos:v0.1.1imagePullPolicy: IfNotPresentports:- name: port-test-01containerPort: 8080protocol: TCP---apiVersion: v1
kind: Service
metadata:labels:app: app-testname: app-testnamespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: app-testports:- name: port01port: 7071targetPort: 8080protocol: TCPtype: ClusterIP# kubectl apply -f app-c24.yaml

http测试

# cat ingress-02.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: demonamespace: test
spec:ingressClassName: nginxrules:- host: www.test.com http:paths:- backend:service:name: app-testport:number: 7071path: /pathType: Prefix# kubectl apply -f ingress-02.yaml# curl http://www.test.com/test
GET     Hello,world-v10
hello,method is get

https测试

# kubectl delete -f ingress-02.yaml
# kubectl create secret tls web-ssl --cert=./web.pem --key=./web-key.pem# cat ingress-01.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: demonamespace: test
spec:ingressClassName: nginxtls:- hosts:- www.demo.com- www.test.comsecretName: web-sslrules:- host: www.test.com http:paths:- backend:service:name: app-testport:number: 7071path: /pathType: Prefix# kubectl apply -f ingress-01.yaml# curl -v -L https://www.test.com/test
*   Trying 192.168.3.180:443...
* Connected to www.test.com (192.168.3.180) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Unknown (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=CN; ST=ZhuMaDian; L=HeNan; O=k8s; OU=System; CN=domain-ssl-test
*  start date: May 14 08:27:00 2023 GMT
*  expire date: Apr 20 08:27:00 2123 GMT
*  subjectAltName: host "www.test.com" matched cert's "*.test.com"
*  issuer: C=CN; ST=shenzhen; L=Gudong; O=k8s; OU=System; CN=Root-CA-gfs
*  SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Unknown (23):
> GET /test HTTP/1.1
> Host: www.test.com
> User-Agent: curl/7.76.1
> Accept: */*
> 
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* TLSv1.2 (IN), TLS header, Unknown (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.23.4
< Date: Mon, 05 Jun 2023 17:02:29 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 40
< Connection: keep-alive
< 
GET     Hello,world-v10
hello,method is get
* Connection #0 to host www.test.com left intacthttp跳转https
# curl -L http://www.test.com/test
GET     Hello,world-v10
hello,method is get

5.5.3 istio ingress

https://istio.io/latest/zh/
建议大家查阅istio官网。

在 Kubernetes 下,对网络流量的管理只能到 Pod 级别,更细粒度的控制,依然得靠应用代码层面来支撑。也就是说,与业务无关的网络控制逻辑依然夹杂在程序员开发的业务代码中。在此背景下,为让程序员更专注于业务代码,服务网格类软件出现,如istio,让运维工作和开发工作更加各自专业本职工作。从某种意上讲,istio是k8s的深度延申。

Istio 使用功能强大的 Envoy 服务代理扩展了 Kubernetes,以建立一个可编程的、可感知的应用程序网络。Istio 与 Kubernetes 和传统工作负载一起使用,为复杂的部署带来了标准的通用流量管理、遥测和安全性。

Istio 由以下组件组成
1。Envoy
每个微服务的 Sidecar 代理,用于处理集群中服务之间以及从服务到外部服务的入口/出口流量。这些代理形成了一个安全的微服务网格,提供了一组丰富的功能,如发现、丰富的第 7 层路由、断路器、策略实施和遥测记录/报告功能。
2。Istiod
Istio 控制平面。它提供服务发现、配置和证书管理。它由以下子组件组成:
Pilot - 负责在运行时配置代理。
Citadel - 负责证书的颁发和轮换。
Galley - 负责在 Istio 中验证、摄取、聚合、转换和分发配置。
3。Operator
该组件提供用户友好的选项来操作 Istio 服务网格。
istio架构,istio官网提供

5.5.3.1 安装istio(从私仓安装)

https://istio.io/latest/zh/docs/setup/getting-started/#download

下载 Istio 发行版

# curl -L https://istio.io/downloadIstio | sh -% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100   101  100   101    0     0    168      0 --:--:-- --:--:-- --:--:--   168
100  4541  100  4541    0     0   3699      0  0:00:01  0:00:01 --:--:--  9914Downloading istio-1.17.2 from https://github.com/istio/istio/releases/download/1.17.2/istio-1.17.2-linux-amd64.tar.gz ...Istio 1.17.2 Download Complete!Istio has been successfully downloaded into the istio-1.17.2 folder on your system.Next Steps:
See https://istio.io/latest/docs/setup/install/ to add Istio to your Kubernetes cluster.To configure the istioctl client tool for your workstation,
add the /root/tp/istio-1.17.2/bin directory to your environment path variable with:export PATH="$PATH:/root/tp/istio-1.17.2/bin"Begin the Istio pre-installation check by running:istioctl x precheck Need more information? Visit https://istio.io/latest/docs/setup/install/ # cp -fr bin/istioctl /sbin/

安装清单修改(从私仓安装)

导出清单
# istioctl manifest generate --set profile=demo --set components.cni.enabled=true > istio.yaml查看配置信息中的镜像
# cat istio.yaml | grep image:image:image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image }}"image: "{{ .ProxyImage }}"image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image }}"image: "{{ .ProxyImage }}"image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"image: "{{ .ProxyImage }}"image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"image: "{{ .ProxyImage }}"image: busybox:1.28image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"image: "{{ .ProxyImage }}"image: "docker.io/istio/install-cni:1.17.2"image: docker.io/istio/proxyv2:1.17.2image: docker.io/istio/proxyv2:1.17.2image: docker.io/istio/pilot:1.17.2将上面的镜像转存在私仓,其中“{{ .ProxyImage }}”为边车注入镜像。
修改配置文件,如下
sed -i 's/{{ .ProxyImage }}/harbor.demo.com\/istio\/proxyv2:1.17.2/g' istio.yaml
sed -i 's/busybox:1.28/harbor.demo.com\/istio\/busybox:1.28/g' istio.yaml
sed -i 's/image: docker.io\/istio/image: harbor.demo.com\/istio/g' istio.yaml
sed -i 's/docker.io\/istio\/install-cni:1.17.2/harbor.demo.com\/istio\/install-cni:1.17.2/g' istio.yaml
查看
# cat istio.yaml | grep image:image:image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image }}"image: "harbor.demo.com/istio/proxyv2:1.17.2"image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image }}"image: "harbor.demo.com/istio/proxyv2:1.17.2"image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"image: "harbor.demo.com/istio/proxyv2:1.17.2"image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"image: "harbor.demo.com/istio/proxyv2:1.17.2"image: harbor.demo.com/istio/busybox:1.28image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"image: "harbor.demo.com/istio/proxyv2:1.17.2"image: "harbor.demo.com/istio/install-cni:1.17.2"image: harbor.demo.com/istio/proxyv2:1.17.2image: harbor.demo.com/istio/proxyv2:1.17.2image: harbor.demo.com/istio/pilot:1.17.2

安装

# kubectl create namespace istio-system    //创建istio-system命名空间
# kubectl apply -f istio.yaml验证安装是否成功
# istioctl verify-install -f istio.yaml  -n istio-system

查看

# kubectl -n istio-system get pod
# kubectl -n istio-system get deploy,ds
# kubectl -n istio-system get svc

5.5.3.2 边车代理注入

https://istio.io/latest/zh/docs/setup/additional-setup/sidecar-injection/
Pod 中注入 Istio Sidecar 的两种方法:使用 istioctl 手动注入或启用 Pod 所属命名空间的 Istio sidecar 注入器自动注入。当 Pod 所属命名空间启用自动注入后,自动注入器会使用准入控制器在创建 Pod 时自动注入代理配置。
自动注入配置

自动注入配置
# kubectl label namespace test istio-injection=enabled  --overwrite=true
namespace/test labeled检查默认策略
在 istio-sidecar-injector configmap 中检查默认注入策略。
# kubectl -n istio-system get configmap istio-sidecar-injector -o jsonpath='{.data.config}' | grep policy:
policy: enabled查看
# kubectl get namespace -L istio-injection
NAME                   STATUS   AGE    ISTIO-INJECTION
default                Active   24d    
istio-system           Active   166m   
kube-node-lease        Active   24d    
kube-public            Active   24d    
kube-system            Active   24d    
kubernetes-dashboard   Active   22d    
metallb-system         Active   5d5h   
test                   Active   16d    enabled解除自动注入sidecar
# kubectl label namespace test istio-injection=disabled --overwrite=true
namespace/test labeled

测试

# cat 1pod.yaml 
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testver: v1replicas: 1template:metadata:name: app-testnamespace: testlabels:app: app-testver: v1spec:containers:- name: httpimage: harbor.demo.com/test/centos:v0.1.1imagePullPolicy: IfNotPresentports:- name: port-test-01containerPort: 8080protocol: TCP
# kubectl apply -f 1pod.yaml

查看

# kubectl describe pod/app-test-6474687d88-2qthn 
...
Init Containers:istio-validation:Container ID:  cri-o://655a8fde38216d8bb183c8b45e533d924fa74106f3e5fb222d39cfe41f0215bfImage:         harbor.demo.com/istio/proxyv2:1.17.2...
Containers:http:Container ID:   cri-o://0c2142ef3680f6c530b5b848ecf5e2ede8312c5e42ff21754031d4435284fde8Image:          harbor.demo.com/test/centos:v0.1.1...istio-proxy:Container ID:  cri-o://a46c0a2deeeff68b8ca5b696903c1d6942b9949317ba99ccc3b251fbb0e6f203Image:         harbor.demo.com/istio/proxyv2:1.17.2

在pod模板中只有一个镜像,但启动模板后被注入两个镜像,且从私仓中拉取。

注入istio-proxy后,pod流量将被代理。

5.5.3.3 http测试

只简单http/https测试,流量治理测试请查看5.7部分。

查看istio入口地址

# kubectl -n istio-system get svc
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                                                                      AGE
istio-egressgateway    ClusterIP      10.10.196.10    <none>          80/TCP,443/TCP                                                               137m
istio-ingressgateway   LoadBalancer   10.10.217.255   192.168.3.181   15021:30721/TCP,80:30406/TCP,443:31152/TCP,31400:30352/TCP,15443:30154/TCP   137m
istiod                 ClusterIP      10.10.79.63     <none>          15010/TCP,15012/TCP,443/TCP,15014/TCP                                        137m

域名解析到istio入口地址

# nslookup -q www.test.com 192.168.3.250
*** Invalid option: q
Server:         192.168.3.250
Address:        192.168.3.250#53Name:   www.test.com
Address: 192.168.3.181

创建入口网关Gateway

# cat gateway-http.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:name: app-test-getwaynamespace: test
spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- www.demo.com- www.test.com

创建VirtualService

# cat virsr.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: app-test-virsrnamespace: test
spec:hosts:- www.test.com- www.demo.comgateways:- app-test-getwayhttp:- match:- uri:prefix: /route:- destination:host: app-testport:

创建pod及svc

# cat deply_pod_svc_centos_1pod.yaml 
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testver: v1replicas: 1template:metadata:name: app-testnamespace: testlabels:app: app-testver: v1spec:containers:- name: httpimage: harbor.demo.com/test/centos:v0.1.1imagePullPolicy: Alwaysports:- name: port-test-01containerPort: 8080protocol: TCP---apiVersion: v1
kind: Service
metadata:labels:app: app-testname: app-testnamespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: app-testports:- name: port01port: 7071targetPort: 8080protocol: TCPtype: ClusterIP

配置应用

# kubectl apply -f gateway-http.yaml -f virsr.yaml -f deply_pod_svc_centos_1pod.yaml

测试效果

# curl -XPOST http://www.test.com/test
POST    Hello,world-v10
hello,method is post

查看istio gateway日志

# kubectl -n istio-system get pod
NAME                                    READY   STATUS    RESTARTS   AGE
istio-cni-node-25vdk                    1/1     Running   0          155m
istio-cni-node-74txt                    1/1     Running   0          155m
istio-cni-node-pbmhn                    1/1     Running   0          155m
istio-egressgateway-bfc9d88d8-7p74f     1/1     Running   0          155m
istio-ingressgateway-775955bfb4-252gt   1/1     Running   0          155m
istiod-555d5d64fb-rnxx2                 1/1     Running   0          155m# kubectl -n istio-system logs pod/istio-ingressgateway-775955bfb4-252gt -f
...
[2023-06-07T09:17:52.962Z] "GET /test HTTP/1.1" 200 - via_upstream - "-" 0 40 3 2 "10.244.36.65" "curl/7.76.1" "e607b10f-dcb6-969e-a41f-758b97572b85" "www.test.com" "10.244.169.141:8080" outbound|7071||app-test.test.svc.cluster.local 10.244.169.133:37806 10.244.169.133:8080 10.244.36.65:34632 - -

查看pod的proxy日志

# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
app-test-6fb979b794-p5h6d   2/2     Running   0          62m# kubectl logs pod/app-test-6fb979b794-p5h6d -c istio-proxy -f
...
[2023-06-07T09:17:52.963Z] "GET /test HTTP/1.1" 200 - via_upstream - "-" 0 40 1 0 "10.244.36.65" "curl/7.76.1" "e607b10f-dcb6-969e-a41f-758b97572b85" "www.test.com" "10.244.169.141:8080" inbound|8080|| 127.0.0.6:47637 10.244.169.141:8080 10.244.36.65:0 outbound_.7071_._.app-test.test.svc.cluster.local default

5.5.3.4 https测试

# kubectl -n istio-system create secret tls web-ssl --cert=./web.pem --key=./web-key.pem
存储证书的secret必须位于名为istio-system的命名空间,否则无法找到。# cat gateway-https.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:name: app-test-getwaynamespace: test
spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- www.demo.com- www.test.comtls:httpsRedirect: true # sends 301 redirect for http requests- port:number: 443name: https-443protocol: HTTPShosts:- www.test.com- www.demo.comtls:mode: SIMPLEcredentialName: web-ssl# kubectl apply -f gateway-https.yaml

测试

# curl -L https://www.test.com/test
GET     Hello,world-v10
hello,method is get
# curl -L http://www.test.com/test
GET     Hello,world-v10
hello,method is get

5.5.3.5 istio dashboard

Istio 和几个遥测应用(如下)做了集成。 遥测能帮您了解服务网格的结构、展示网络的拓扑结构、分析网格的健康状态。

# tree samples/addons/
samples/addons/
├── extras
│   ├── prometheus-operator.yaml
│   ├── prometheus_vm_tls.yaml
│   ├── prometheus_vm.yaml
│   ├── skywalking.yaml
│   └── zipkin.yaml
├── grafana.yaml
├── jaeger.yaml
├── kiali.yaml
├── prometheus.yaml
└── README.md
组件类别组件说明
服务拓扑结构显示类Kiali,会调用jaeger/Prometheus等,建议先安装jaeger/Prometheus
监控类Prometheus:数据采集
Grafana:可视化
服务追踪类Zipkin:由Twitter开发,基于语言的探针
jaeger:由Uber推出的一款开源分布式追踪系统,兼容OpenTracing API
skywalking:基于语言的探针

提示:
istio集成的Prometheus/Grafana版本低于其官方版本,建议采用官方版本

准备
1。三个域名(kiaki.test.com、prometheus-istio.test.com、jaeger.test.com),指向istio-ingress.
2。将所需应用的镜像转存私仓。
2。创建gw和vs,用于暴露服务。

# cat istio-dashboard.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:name: istio-ui-gwnamespace: istio-system
spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- kiaki.test.com- prometheus.test.com- jaeger.test.com---apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: istio-ui-kialinamespace: istio-system
spec:hosts:- kiaki.test.comgateways:- istio-ui-gwhttp:- match:- uri:prefix: /route:- destination:host: kialiport:number: 20001
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: istio-ui-prometheusnamespace: istio-system
spec:hosts:- prometheus-istio.test.comgateways:- istio-ui-gwhttp:- match:- uri:prefix: /route:- destination:host: prometheusport:number: 9090---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: istio-ui-jaegernamespace: istio-system
spec:hosts:- jaeger.test.comgateways:- istio-ui-gwhttp:- match:- uri:prefix: /route:- destination:host: tracingport:number: 80

安装

kubectl apply -f istio-dashboard.yaml
kubectl apply -f prometheus.yaml 
kubectl apply -f jaeger.yaml 
kubectl -n istio-system get svc

测试

# for i in $(seq 1 100);do curl http://www.test.com/test;done

查看
http://kiaki.test.com
在这里插入图片描述
http://jaeger.test.com
在这里插入图片描述

5.6 存储持久化

https://kubernetes.io/docs/concepts/storage/volumes

k8s的存储方案有很多种,如ceph、glusterfs、cinder、nfs等等,支持CSI(Container Storage Interface ,第三方容器存储接口协议)。
本文以cehph为主。
k8s存储持久化,涉及较多概念,如:
在这里插入图片描述

5.6.1 准备

下载cephcsi

# git clone https://github.com/ceph/ceph-csi.git# tree ceph-csi
ceph-csi/
├── actions
├── api
├── assets
├── build.env
├── charts
├── cmd
├── deploy
│   ├── ceph-conf.yaml
│   ├── cephcsi
│   ├── cephfs
│   ├── csi-config-map-sample.yaml
│   ├── Makefile
│   ├── nfs
│   ├── rbd
│   ├── scc.yaml
│   └── service-monitor.yaml
├── deploy.sh
├── docs
├── e2e
├── examples
│   ├── ceph-conf.yaml
│   ├── cephfs
│   ├── csi-config-map.yaml
│   ├── csi-kms-config-map.yaml
│   ├── kms
│   ├── nfs
│   ├── rbd
│   └── README.md
├── go.mod
├── go.sum
├── internal
├── LICENSE
├── Makefile
├── README.md
├── scripts
├── tools
├── troubleshooting
└── vendor

转存镜像到本地私仓

# find ceph-csi/deploy/{cephfs,rbd} | xargs grep image:  > image.txt
# cat image.txt | cut -d' ' -f12 | sort | uniq
quay.io/cephcsi/cephcsi:canary
registry.k8s.io/sig-storage/csi-attacher:v4.3.0
registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.8.0
registry.k8s.io/sig-storage/csi-provisioner:v3.5.0
registry.k8s.io/sig-storage/csi-resizer:v1.8.0
registry.k8s.io/sig-storage/csi-snapshotter:v6.2.2

可以从国内镜像源拉取

# find ceph-csi/deploy/{cephfs,rbd} | xargs grep image:  > image.txt
# cat image.txt | cut -d' ' -f12 | sort | uniq
quay.io/cephcsi/cephcsi:canary
registry.k8s.io/sig-storage/csi-attacher:v4.3.0
registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.8.0
registry.k8s.io/sig-storage/csi-provisioner:v3.5.0
registry.k8s.io/sig-storage/csi-resizer:v1.8.0
registry.k8s.io/sig-storage/csi-snapshotter:v6.2.2

转存后记得更改如下清单文件中的镜像拉取地址为私仓。

# cat image.txt
ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml:          image: registry.k8s.io/sig-storage/csi-provisioner:v3.5.0
ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml:          image: registry.k8s.io/sig-storage/csi-resizer:v1.8.0
ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml:          image: registry.k8s.io/sig-storage/csi-snapshotter:v6.2.2
ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml:          image: quay.io/cephcsi/cephcsi:canary
ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml:          image: quay.io/cephcsi/cephcsi:canary
ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin.yaml:          image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.8.0
ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin.yaml:          image: quay.io/cephcsi/cephcsi:canary
ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin.yaml:          image: quay.io/cephcsi/cephcsi:canary
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml:          image: registry.k8s.io/sig-storage/csi-provisioner:v3.5.0
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml:          image: registry.k8s.io/sig-storage/csi-snapshotter:v6.2.2
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml:          image: registry.k8s.io/sig-storage/csi-attacher:v4.3.0
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml:          image: registry.k8s.io/sig-storage/csi-resizer:v1.8.0
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml:          image: quay.io/cephcsi/cephcsi:canary
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml:          image: quay.io/cephcsi/cephcsi:canary
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml:          image: quay.io/cephcsi/cephcsi:canary
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin.yaml:          image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.8.0
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin.yaml:          image: quay.io/cephcsi/cephcsi:canary
ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin.yaml:          image: quay.io/cephcsi/cephcsi:canary

可采用如下脚本更改,例如私仓地址为harbor.demo.com/ceph.

sed -i 's/image: registry.k8s.io\/sig-storage/image: harbor.demo.com\/ceph/g'	ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml
sed -i 's/image: registry.k8s.io\/sig-storage/image: harbor.demo.com\/ceph/g'	ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin.yaml
sed -i 's/image: quay.io\/cephcsi/image: harbor.demo.com\/ceph/g'		ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml
sed -i 's/image: quay.io\/cephcsi/image: harbor.demo.com\/ceph/g'		ceph-csi/deploy/cephfs/kubernetes/csi-cephfsplugin.yaml
sed -i 's/image: registry.k8s.io\/sig-storage/image: harbor.demo.com\/ceph/g'	ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml
sed -i 's/image: registry.k8s.io\/sig-storage/image: harbor.demo.com\/ceph/g'	ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin.yaml
sed -i 's/image: quay.io\/cephcsi/image: harbor.demo.com\/ceph/g'		ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml
sed -i 's/image: quay.io\/cephcsi/image: harbor.demo.com\/ceph/g'		ceph-csi/deploy/rbd/kubernetes/csi-rbdplugin.yaml

创建命名空间,并配置为当前上下文的默认命名空间。

kubectl create namespace ceph-csi
kubectl config set-context kubernetes-admin@kubernetes --namespace='ceph-csi'

在dynamic/ceph-csi/deploy/cephfs/kubernetes中的csi-nodeplugin-rbac.yaml和csi-provisioner-rbac.yaml文件中没有给k8s资源在定义时没指定命令空间,此时会采用当前默认的命名空间。

配置csi认证方式

# cat ceph-csi/deploy/ceph-conf.yaml 
---
# This is a sample configmap that helps define a Ceph configuration as required
# by the CSI plugins.# Sample ceph.conf available at
# https://github.com/ceph/ceph/blob/master/src/sample.ceph.conf Detailed
# documentation is available at
# https://docs.ceph.com/en/latest/rados/configuration/ceph-conf/
apiVersion: v1
kind: ConfigMap
data:ceph.conf: |[global]auth_cluster_required = cephxauth_service_required = cephxauth_client_required = cephx# keyring is a required key and its value should be emptykeyring: |
metadata:name: ceph-config# kubectl apply -f ceph-csi/deploy/ceph-conf.yaml

配置csi-config-map

# ceph mon dump
epoch 2
fsid 9b7095ab-5193-420c-b2fb-2d343c57ef52
last_changed 2023-06-04T09:09:31.753367+0800
created 2023-06-04T01:27:47.063896+0800
min_mon_release 17 (quincy)
election_strategy: 1
0: [v2:10.2.20.90:3300/0,v1:10.2.20.90:6789/0] mon.mon1
dumped monmap epoch 2cat > ceph-csi/deploy/csi-config-map.yaml << 'EOF'
apiVersion: v1
kind: ConfigMap
data:config.json: |-[{"clusterID": "9b7095ab-5193-420c-b2fb-2d343c57ef52","monitors": ["10.2.20.90:6789"]}]
metadata:name: ceph-csi-config
EOF# kubectl apply -f ceph-csi/deploy/csi-config-map.yaml

配置CSI-KMS-config-map

ceph-csi 还需要一个额外的 ConfigMap 对象来 定义密钥管理服务 (KMS) 提供程序详细信息。
如果未设置 KMS, CSI-KMS-config-map.yaml 文件按以下配置或参考示例 在 https://github.com/ceph/ceph-csi/tree/master/examples/kms

# cat <<EOF > ceph-csi/deploy/csi-kms-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
data:config.json: |-{}
metadata:name: ceph-csi-encryption-kms-config
EOF# kubectl apply -f ceph-csi/deploy/csi-kms-config-map.yaml

5.6.2 ceph-fs csi配置

5.6.2.1 安装ceph-fs csi

进入cephfs插件目录

# cd ceph-csi/deploy/cephfs/kubernetes
# tree .
.
├── csi-cephfsplugin-provisioner.yaml
├── csi-cephfsplugin.yaml
├── csi-config-map.yaml
├── csidriver.yaml
├── csi-nodeplugin-rbac.yaml
└── csi-provisioner-rbac.yaml

更改清单文件中的命名空间名称

# NAMESPACE=ceph-csi
# sed -r -i "s/namespace: [^ ]+/namespace: $NAMESPACE/g" ./*.yaml

安装

kubectl apply -f ./csidriver.yaml
kubectl apply -f ./csi-provisioner-rbac.yaml
kubectl apply -f ./csi-nodeplugin-rbac.yaml
kubectl apply -f ./csi-cephfsplugin-provisioner.yaml
kubectl apply -f ./csi-cephfsplugin.yaml

查看

# kubectl get pod
NAME                                            READY   STATUS    RESTARTS   AGE
csi-cephfsplugin-5bwgs                          3/3     Running   0          82s
csi-cephfsplugin-provisioner-64b57b7f4c-d4hr7   5/5     Running   0          83s
csi-cephfsplugin-provisioner-64b57b7f4c-hwcd4   0/5     Pending   0          82s  # 由于master节点不支持普通pod安装所制。
csi-cephfsplugin-provisioner-64b57b7f4c-x6qtb   5/5     Running   0          82s
csi-cephfsplugin-q5wks                          3/3     Running   0          82s

5.6.2.2 sc存储类配置

提示:
sc/pvc对像的命名空间与用户pod相同。但不必与ceph-csi的pod在同一个命名空间。本例中:ceph-csi在ceph-fs命名空间,而Secret/sc/pv/pvc在test命名空间。

修改上下文的默认命名空间

# kubectl config set-context kubernetes-admin@kubernetes --namespace='test'

创建fs卷

ceph osd pool create k8s-metadata 4 4
ceph osd pool create k8s-data 4 4
ceph fs new k8s-fs k8s-metadata k8s-data# ceph fs ls
name: k8s-fs, metadata pool: k8s-metadata, data pools: [k8s-data ]

重要提示:
在建立fs卷前,一定要查看下mds进程的个数和fs卷的个数,只有“fs卷的个数 < mds进程的个数”时才可以创建。若不能创建,就使用已存在的fs卷。或删除某个卷再建新卷。

配置csi-fs-secret
csi会通过pod访问ceph集群,使用client.admin

查看管理员密码
# ceph auth get client.admin
[client.admin]key = AQCwXntkCw+CGBAA/mdug0WT2jYDAFEN8tATOA==caps mds = "allow *"caps mgr = "allow *"caps mon = "allow *"caps osd = "allow *"创建访问fs卷的用户
# ceph auth get-or-create client.k8sfs mon "allow * fsname=k8s-fs" mds "allow * fsname=k8s-fs" osd "allow * tag cephfs data=k8s-fs"
[client.k8sfs]key = AQCX94FkmzL0KRAA3t/G7S7Qn631V9YeUYMuWQ==# ceph auth get client.k8sfs
[client.k8sfs]key = AQCX94FkmzL0KRAA3t/G7S7Qn631V9YeUYMuWQ==caps mds = "allow * fsname=k8s-fs"caps mon = "allow * fsname=k8s-fs"caps osd = "allow * tag cephfs data=k8s-fs"配置secret
cat > ./csi-fs-secret.yaml << 'EOF'
---
apiVersion: v1
kind: Secret
metadata:name: csi-cephfs-secretnamespace: test
stringData:# Required for statically provisioned volumesuserID: k8sfsuserKey: AQCX94FkmzL0KRAA3t/G7S7Qn631V9YeUYMuWQ==# Required for dynamically provisioned volumesadminID: adminadminKey: AQCwXntkCw+CGBAA/mdug0WT2jYDAFEN8tATOA==
EOF# kubectl apply -f csi-fs-secret.yaml
此csi-cephfs-secret供sc存储类使用。

配置ceph-fs存储类

# cat storageclass.yaml 
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: csi-cephfs-scnamespace: test
provisioner: cephfs.csi.ceph.com
parameters:# (required) String representing a Ceph cluster to provision storage from.# Should be unique across all Ceph clusters in use for provisioning,# cannot be greater than 36 bytes in length, and should remain immutable for# the lifetime of the StorageClass in use.# Ensure to create an entry in the configmap named ceph-csi-config, based on# csi-config-map-sample.yaml, to accompany the string chosen to# represent the Ceph cluster in clusterID belowclusterID: 9b7095ab-5193-420c-b2fb-2d343c57ef52# (required) CephFS filesystem name into which the volume shall be created# eg: fsName: myfsfsName: k8s-fs# (optional) Ceph pool into which volume data shall be stored# pool: <cephfs-data-pool># (optional) Comma separated string of Ceph-fuse mount options.# For eg:# fuseMountOptions: debug# (optional) Comma separated string of Cephfs kernel mount options.# Check man mount.ceph for mount options. For eg:# kernelMountOptions: readdir_max_bytes=1048576,norbytes# The secrets have to contain user and/or Ceph admin credentials.csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secretcsi.storage.k8s.io/provisioner-secret-namespace: testcsi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secretcsi.storage.k8s.io/controller-expand-secret-namespace: testcsi.storage.k8s.io/node-stage-secret-name: csi-cephfs-secretcsi.storage.k8s.io/node-stage-secret-namespace: test# (optional) The driver can use either ceph-fuse (fuse) or# ceph kernelclient (kernel).# If omitted, default volume mounter will be used - this is# determined by probing for ceph-fuse and mount.ceph# mounter: kernel# (optional) Prefix to use for naming subvolumes.# If omitted, defaults to "csi-vol-".# volumeNamePrefix: "foo-bar-"# (optional) Boolean value. The PVC shall be backed by the CephFS snapshot# specified in its data source. `pool` parameter must not be specified.# (defaults to `true`)# backingSnapshot: "false"# (optional) Instruct the plugin it has to encrypt the volume# By default it is disabled. Valid values are "true" or "false".# A string is expected here, i.e. "true", not true.# encrypted: "true"# (optional) Use external key management system for encryption passphrases by# specifying a unique ID matching KMS ConfigMap. The ID is only used for# correlation to configmap entry.# encryptionKMSID: <kms-config-id>reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:- debug# kubectl apply -f storageclass.yaml
# kubectl get sc -n test
NAME            PROVISIONER           RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
csi-cephfs-sc   cephfs.csi.ceph.com   Delete          Immediate           true                   72s

5.6.2.3 无状态部署测试

配置PVC

# cat pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: csi-cephfs-pvcnamespace: test
spec:storageClassName: csi-cephfs-scaccessModes:- ReadWriteManyresources:requests:storage: 2Gi# kubectl apply -f pvc.yaml 
# kubectl get sc,pv,pvc -n test
NAME                                        PROVISIONER           RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
storageclass.storage.k8s.io/csi-cephfs-sc   cephfs.csi.ceph.com   Delete          Immediate           true                   2m52sNAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS    REASON   AGE
persistentvolume/pvc-2c474ef8-d076-4d64-8cf4-75c47d868d67   2Gi        RWX            Delete           Bound    test/csi-cephfs-pvc   csi-cephfs-sc            9sNAME                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
persistentvolumeclaim/csi-cephfs-pvc   Bound    pvc-2c474ef8-d076-4d64-8cf4-75c47d868d67   2Gi        RWX            csi-cephfs-sc   10s

pod模板配置

# cat test-pod-1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testver: v1replicas: 1template:metadata:name: app-testnamespace: testlabels:app: app-testver: v1spec:volumes:- name: mypvc-cephfspersistentVolumeClaim:claimName: csi-cephfs-pvcreadOnly: falsecontainers:- name: httpimage: harbor.demo.com/web/centos:v0.1imagePullPolicy: IfNotPresentvolumeMounts:- name: mypvc-cephfsmountPath: /home/cephfsports:- name: port-test-01containerPort: 8080protocol: TCP# kubectl apply -f test-pod-1.yaml          

查看

# kubectl get pod -n test
NAME                        READY   STATUS    RESTARTS   AGE
app-test-7fc767985c-cbc8k   2/2     Running   0          10s
# kubectl -n test exec po/app-test-7fc767985c-cbc8k -- df -Th
Filesystem           Type            Size      Used Available Use% Mounted on
overlay              overlay        27.2G      6.7G     20.5G  25% /
tmpfs                tmpfs          64.0M         0     64.0M   0% /dev
shm                  tmpfs          64.0M         0     64.0M   0% /dev/shm
tmpfs                tmpfs         730.8M     10.6M    720.2M   1% /etc/resolv.conf
tmpfs                tmpfs         730.8M     10.6M    720.2M   1% /etc/hostname
tmpfs                tmpfs         730.8M     10.6M    720.2M   1% /run/.containerenv
10.2.20.90:6789:/volumes/csi/csi-vol-11adc09a-f118-44ee-81ca-3b80427cbcb6/a84f61f3-d0a1-4952-925b-987bc6dbe401     //静态PVceph            2.0G         0      2.0G   0% /home/cephfs
/dev/mapper/rl-root  xfs            27.2G      6.7G     20.5G  25% /etc/hosts
/dev/mapper/rl-root  xfs            27.2G      6.7G     20.5G  25% /dev/termination-log
tmpfs                tmpfs           3.5G     12.0K      3.5G   0% /var/run/secrets/kubernetes.io/serviceaccount
devtmpfs             devtmpfs        4.0M         0      4.0M   0% /proc/kcore
devtmpfs             devtmpfs        4.0M         0      4.0M   0% /proc/keys
devtmpfs             devtmpfs        4.0M         0      4.0M   0% /proc/timer_list

若pod多副本,它们之间是共享存储。

5.6.2.4 有状态部署测试

采用卷模板为每一个pod副本提供一个pvc.

# cat test-pod-2.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testver: v1replicas: 3template:metadata:name: app-testnamespace: testlabels:app: app-testver: v1spec:containers:- name: httpimage: harbor.demo.com/web/centos:v0.1imagePullPolicy: IfNotPresentvolumeMounts:- name: test-sfmountPath: /home/cephfsports:- name: port-test-01containerPort: 8080protocol: TCPvolumeClaimTemplates:               - metadata:name: test-sfspec:accessModes: [ "ReadWriteMany" ]storageClassName: csi-cephfs-scresources:requests:storage: 1Gi # kubectl apply -f test-pod-2.yaml           

查看

# kubectl -n test get sc,pv,pvc
NAME                                        PROVISIONER           RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
storageclass.storage.k8s.io/csi-cephfs-sc   cephfs.csi.ceph.com   Delete          Immediate           true                   10hNAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS    REASON   AGE
persistentvolume/pvc-34d03e58-bd10-4a94-b427-83cd1de389b2   1Gi        RWX            Delete           Bound    test/test-sf-app-test-2   csi-cephfs-sc            9h
persistentvolume/pvc-7a85a6f6-c48c-4474-a498-eaeb802dd331   1Gi        RWX            Delete           Bound    test/test-sf-app-test-1   csi-cephfs-sc            9h
persistentvolume/pvc-f276331a-416f-45af-82eb-c008cf57839a   1Gi        RWX            Delete           Bound    test/test-sf-app-test-0   csi-cephfs-sc            9hNAME                                       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
persistentvolumeclaim/test-sf-app-test-0   Bound    pvc-f276331a-416f-45af-82eb-c008cf57839a   1Gi        RWX            csi-cephfs-sc   9h
persistentvolumeclaim/test-sf-app-test-1   Bound    pvc-7a85a6f6-c48c-4474-a498-eaeb802dd331   1Gi        RWX            csi-cephfs-sc   9h
persistentvolumeclaim/test-sf-app-test-2   Bound    pvc-34d03e58-bd10-4a94-b427-83cd1de389b2   1Gi        RWX            csi-cephfs-sc   9h

5.6.3 ceph-rbd csi配置

5.6.3.1 安装ceph-rbd csi

进入rbd插件目录
# cd ceph-csi/deploy/rbd/kubernetes
# tree .
.
├── csi-config-map.yaml
├── csidriver.yaml
├── csi-nodeplugin-rbac.yaml
├── csi-provisioner-rbac.yaml
├── csi-rbdplugin-provisioner.yaml
└── csi-rbdplugin.yaml更改清单文件中的命名空间名称
# NAMESPACE=ceph-csi
# sed -r -i "s/namespace: [^ ]+/namespace: $NAMESPACE/g" ./*.yaml
# kubectl config set-context kubernetes-admin@kubernetes --namespace='ceph-csi'安装(安装前需将镜像转存私仓)
kubectl apply -f ./csi-provisioner-rbac.yaml
kubectl apply -f ./csi-nodeplugin-rbac.yaml
kubectl apply -f ./csi-rbdplugin-provisioner.yaml
kubectl apply -f ./csi-rbdplugin.yaml

查看

# kubectl -n ceph-csi get pod
NAME                                            READY   STATUS    RESTARTS   AGE
csi-rbdplugin-provisioner-7b657bbc4-bq9lv       0/7     Pending   0          3h9m
csi-rbdplugin-provisioner-7b657bbc4-rrtr5       7/7     Running   0          3h9m
csi-rbdplugin-provisioner-7b657bbc4-sbbkr       7/7     Running   0          3h9m
csi-rbdplugin-pw76p                             3/3     Running   0          3h9m
csi-rbdplugin-tm8st                             3/3     Running   0          3h9m

5.6.3.2 sc存储类配置

提示:
sc/pvc对像的命名空间与用户pod相同。但不必与ceph-csi的pod在同一个命名空间。本例中:ceph-csi在ceph-fs命名空间,而Secret/sc/pv/pvc在test命名空间。

修改上下文的默认命名空间

# kubectl config set-context kubernetes-admin@kubernetes --namespace='test'

创建k8s的rbd池

# ceph osd pool create k8s-pool 8 8
# rbd pool init k8s-pool

配置csi-rbd-secret

创建访问pool的用户
# ceph auth get-or-create client.k8srbd mon 'profile rbd' mgr 'profile rbd pool=k8s-poold'  osd 'profile rbd pool=k8s-pool' 
[client.k8srbd]key = AQDZ44Fk2SGfJRAAGOQnJFAGzDlRw00r/s+s2A==
此值用于k8s中的secret建立。
# ceph auth get client.k8srbd
[client.k8srbd]key = AQDZ44Fk2SGfJRAAGOQnJFAGzDlRw00r/s+s2A==caps mgr = "profile rbd pool=k8s-poold"caps mon = "profile rbd"caps osd = "profile rbd pool=k8s-pool"# cat > ./csi-rbd-secret.yaml << 'EOF'
apiVersion: v1
kind: Secret
metadata:name: csi-rbd-secretnamespace: test
stringData:userID: k8srbduserKey: AQDZ44Fk2SGfJRAAGOQnJFAGzDlRw00r/s+s2A==
EOF# kubectl apply -f csi-rbd-secret.yaml

配置ceph-rbd存储类

# cat storageclass.yaml 
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: csi-rbd-scnamespace: test
provisioner: rbd.csi.ceph.com
# If topology based provisioning is desired, delayed provisioning of
# PV is required and is enabled using the following attribute
# For further information read TODO<doc>
# volumeBindingMode: WaitForFirstConsumer
parameters:# (required) String representing a Ceph cluster to provision storage from.# Should be unique across all Ceph clusters in use for provisioning,# cannot be greater than 36 bytes in length, and should remain immutable for# the lifetime of the StorageClass in use.# Ensure to create an entry in the configmap named ceph-csi-config, based on# csi-config-map-sample.yaml, to accompany the string chosen to# represent the Ceph cluster in clusterID belowclusterID: 9b7095ab-5193-420c-b2fb-2d343c57ef52# (optional) If you want to use erasure coded pool with RBD, you need to# create two pools. one erasure coded and one replicated.# You need to specify the replicated pool here in the `pool` parameter, it is# used for the metadata of the images.# The erasure coded pool must be set as the `dataPool` parameter below.# dataPool: <ec-data-pool># (required) Ceph pool into which the RBD image shall be created# eg: pool: rbdpoolpool: k8s-pool# (optional) RBD image features, CSI creates image with image-format 2 CSI# RBD currently supports `layering`, `journaling`, `exclusive-lock`,# `object-map`, `fast-diff`, `deep-flatten` features.# Refer https://docs.ceph.com/en/latest/rbd/rbd-config-ref/#image-features# for image feature dependencies.# imageFeatures: layering,journaling,exclusive-lock,object-map,fast-diffimageFeatures: "layering"# (optional) Options to pass to the `mkfs` command while creating the# filesystem on the RBD device. Check the man-page for the `mkfs` command# for the filesystem for more details. When `mkfsOptions` is set here, the# defaults will not be used, consider including them in this parameter.## The default options depend on the csi.storage.k8s.io/fstype setting:# - ext4: "-m0 -Enodiscard,lazy_itable_init=1,lazy_journal_init=1"# - xfs: "-onouuid -K"## mkfsOptions: "-m0 -Ediscard -i1024"# (optional) Specifies whether to try other mounters in case if the current# mounter fails to mount the rbd image for any reason. True means fallback# to next mounter, default is set to false.# Note: tryOtherMounters is currently useful to fallback from krbd to rbd-nbd# in case if any of the specified imageFeatures is not supported by krbd# driver on node scheduled for application pod launch, but in the future this# should work with any mounter type.# tryOtherMounters: false# (optional) mapOptions is a comma-separated list of map options.# For krbd options refer# https://docs.ceph.com/docs/master/man/8/rbd/#kernel-rbd-krbd-options# For nbd options refer# https://docs.ceph.com/docs/master/man/8/rbd-nbd/#options# Format:# mapOptions: "<mounter>:op1,op2;<mounter>:op1,op2"# An empty mounter field is treated as krbd type for compatibility.# eg:# mapOptions: "krbd:lock_on_read,queue_depth=1024;nbd:try-netlink"# (optional) unmapOptions is a comma-separated list of unmap options.# For krbd options refer# https://docs.ceph.com/docs/master/man/8/rbd/#kernel-rbd-krbd-options# For nbd options refer# https://docs.ceph.com/docs/master/man/8/rbd-nbd/#options# Format:# unmapOptions: "<mounter>:op1,op2;<mounter>:op1,op2"# An empty mounter field is treated as krbd type for compatibility.# eg:# unmapOptions: "krbd:force;nbd:force"# The secrets have to contain Ceph credentials with required access# to the 'pool'.csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secretcsi.storage.k8s.io/provisioner-secret-namespace: testcsi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secretcsi.storage.k8s.io/controller-expand-secret-namespace: testcsi.storage.k8s.io/node-stage-secret-name: csi-rbd-secretcsi.storage.k8s.io/node-stage-secret-namespace: test# (optional) Specify the filesystem type of the volume. If not specified,# csi-provisioner will set default as `ext4`.csi.storage.k8s.io/fstype: ext4# (optional) uncomment the following to use rbd-nbd as mounter# on supported nodes# mounter: rbd-nbd# (optional) ceph client log location, eg: rbd-nbd# By default host-path /var/log/ceph of node is bind-mounted into# csi-rbdplugin pod at /var/log/ceph mount path. This is to configure# target bindmount path used inside container for ceph clients logging.# See docs/rbd-nbd.md for available configuration options.# cephLogDir: /var/log/ceph# (optional) ceph client log strategy# By default, log file belonging to a particular volume will be deleted# on unmap, but you can choose to just compress instead of deleting it# or even preserve the log file in text format as it is.# Available options `remove` or `compress` or `preserve`# cephLogStrategy: remove# (optional) Prefix to use for naming RBD images.# If omitted, defaults to "csi-vol-".# volumeNamePrefix: "foo-bar-"# (optional) Instruct the plugin it has to encrypt the volume# By default it is disabled. Valid values are "true" or "false".# A string is expected here, i.e. "true", not true.# encrypted: "true"# (optional) Select the encryption type when encrypted: "true" above.# Valid values are:#   "file": Enable file encryption on the mounted filesystem#   "block": Encrypt RBD block device# When unspecified assume type "block". "file" and "block" are# mutally exclusive.# encryptionType: "block"# (optional) Use external key management system for encryption passphrases by# specifying a unique ID matching KMS ConfigMap. The ID is only used for# correlation to configmap entry.# encryptionKMSID: <kms-config-id># Add topology constrained pools configuration, if topology based pools# are setup, and topology constrained provisioning is required.# For further information read TODO<doc># topologyConstrainedPools: |#   [{"poolName":"pool0",#     "dataPool":"ec-pool0" # optional, erasure-coded pool for data#     "domainSegments":[#       {"domainLabel":"region","value":"east"},#       {"domainLabel":"zone","value":"zone1"}]},#    {"poolName":"pool1",#     "dataPool":"ec-pool1" # optional, erasure-coded pool for data#     "domainSegments":[#       {"domainLabel":"region","value":"east"},#       {"domainLabel":"zone","value":"zone2"}]},#    {"poolName":"pool2",#     "dataPool":"ec-pool2" # optional, erasure-coded pool for data#     "domainSegments":[#       {"domainLabel":"region","value":"west"},#       {"domainLabel":"zone","value":"zone1"}]}#   ]# Image striping, Refer https://docs.ceph.com/en/latest/man/8/rbd/#striping# For more details# (optional) stripe unit in bytes.# stripeUnit: <># (optional) objects to stripe over before looping.# stripeCount: <># (optional) The object size in bytes.# objectSize: <>
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:- discard# kubectl apply -f storageclass.yaml

5.6.3.3 无状态部署测试

PVC配置

# cat test-pvc-block-fs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: ceph-pvc-rbd-fsnamespace: test
spec:storageClassName: csi-rbd-scaccessModes:- ReadWriteOncevolumeMode: Filesystemresources:requests:storage: 2Gi# kubectl apply -f test-pvc-block-fs.yaml

查看

# kubectl get sc,pv,pvc
NAME                                        PROVISIONER           RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
storageclass.storage.k8s.io/csi-cephfs-sc   cephfs.csi.ceph.com   Delete          Immediate           true                   11h
storageclass.storage.k8s.io/csi-rbd-sc      rbd.csi.ceph.com      Delete          Immediate           true                   82mNAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                   STORAGECLASS   REASON   AGE
persistentvolume/pvc-6d68f26c-28e5-45f2-9a3f-f9ff77769684   2Gi        RWO            Delete           Bound      test/ceph-pvc-rbd-fs    csi-rbd-sc              39s
persistentvolume/pvc-89aa9a09-1aa1-42f7-b8b0-58061953d681   3Gi        RWO            Delete           Released   test/ceph-pvc-rbd-raw   csi-rbd-sc              37mNAME                                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/ceph-pvc-rbd-fs   Bound    pvc-6d68f26c-28e5-45f2-9a3f-f9ff77769684   2Gi        RWO            csi-rbd-sc     40s

pod模板

# cat test-pod-fs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testreplicas: 1template:metadata:name: app-testnamespace: testlabels:app: app-testspec:volumes:- name: ceph-rbd-fspersistentVolumeClaim:claimName: ceph-pvc-rbd-fscontainers:- name: httpimage: harbor.demo.com/web/centos:v0.1imagePullPolicy: IfNotPresentvolumeMounts:- name: ceph-rbd-fsmountPath: /home/cephreadOnly: false

查看

# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
app-test-68b7fccb49-g2mvz   1/1     Running   0          46s# kubectl exec pod/app-test-68b7fccb49-mrb7b -- df -Th
Filesystem           Type            Size      Used Available Use% Mounted on
overlay              overlay        27.2G      6.7G     20.5G  25% /
tmpfs                tmpfs          64.0M         0     64.0M   0% /dev
shm                  tmpfs          64.0M         0     64.0M   0% /dev/shm
tmpfs                tmpfs         730.8M     11.3M    719.5M   2% /etc/resolv.conf
tmpfs                tmpfs         730.8M     11.3M    719.5M   2% /etc/hostname
tmpfs                tmpfs         730.8M     11.3M    719.5M   2% /run/.containerenv
/dev/rbd0            ext4            1.9G     28.0K      1.9G   0% /home/ceph     成功
/dev/mapper/rl-root  xfs            27.2G      6.7G     20.5G  25% /etc/hosts
/dev/mapper/rl-root  xfs            27.2G      6.7G     20.5G  25% /dev/termination-log
tmpfs                tmpfs           3.5G     12.0K      3.5G   0% /var/run/secrets/kubernetes.io/serviceaccount
devtmpfs             devtmpfs        4.0M         0      4.0M   0% /proc/kcore
devtmpfs             devtmpfs        4.0M         0      4.0M   0% /proc/keys
devtmpfs             devtmpfs        4.0M         0      4.0M   0% /proc/timer_list

5.6.3.4 有状态部署测试

pod模板

apiVersion: apps/v1
kind: StatefulSet
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testver: v1replicas: 3template:metadata:name: app-testnamespace: testlabels:app: app-testver: v1spec:containers:- name: httpimage: harbor.demo.com/web/centos:v0.1imagePullPolicy: IfNotPresentvolumeMounts:- name: test-sfmountPath: /home/cephfsports:- name: port-test-01containerPort: 8080protocol: TCPvolumeClaimTemplates:               - metadata:name: test-sfspec:accessModes: [ "ReadWriteOnce" ]storageClassName: csi-rbd-scresources:requests:storage: 1Gi            

查看pvc

# kubectl get pvc
NAME                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
test-sf-app-test-0   Bound    pvc-ef0e2be8-6192-4e27-aab4-1a1482dc2077   1Gi        RWO            csi-rbd-sc     9m38s
test-sf-app-test-1   Bound    pvc-e92e1ec2-497a-4c03-ba5a-b0fc4a30aa5f   1Gi        RWO            csi-rbd-sc     9m22s
test-sf-app-test-2   Bound    pvc-56bbbbf9-ac02-49cf-a5ae-b0b979fd1d59   1Gi        RWO            csi-rbd-sc     9m17s

查看ceph

# rbd ls k8s-pool
csi-vol-5fd326fa-45a1-460f-911a-c47d004fd215
csi-vol-c0dd0862-a4cf-488e-8100-e5e79c4d98e1
csi-vol-e95e63d1-a943-4003-9e41-c8aac0068ac8

5.7 测试

5.7.1 istio流量治理

Istio流量治理是Istio的核心能力,通过服务级别的配置,如使用Istio可以管理服务网格的服务发现、流量路由、负载均衡,实现蓝绿发布(A/B发布)、灰度发布以及百分比流量策略发布等,Istio 还可以实现诸如故障注入、熔断限流、超时重试等流量治理功能。

路由规则是将特定流量子集路由到指定目标地址的强大工具。
您可以在流量端口、header 字段、URI 等内容上面设置匹配条件。

5.7.1.1 微服务准备

三个微服务配置

# cat deply_pod_svc_centos_3pod.yaml 
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-test-1namespace: test
spec:selector:matchLabels:app: app-testver: v1replicas: 1template:metadata:name: app-test-1namespace: testlabels:app: app-testver: v1spec:containers:- name: httpimage: harbor.demo.com/web/centos:v0.1imagePullPolicy: IfNotPresentports:- name: port-test-01containerPort: 8080protocol: TCP
---
apiVersion: apps/v1
kind: Deployment 
metadata:name: app-test-2namespace: test
spec:selector:matchLabels:app: app-testver: v2replicas: 1template:metadata:name: app-test-2namespace: testlabels:app: app-testver: v2spec:containers:- name: httpimage: harbor.demo.com/web/centos:v0.2imagePullPolicy: IfNotPresentports:- name: port-test-02containerPort: 8080protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:name: app-test-3namespace: test
spec:selector:matchLabels:app: app-testver: v3replicas: 1template:metadata:name: app-test-3namespace: testlabels:app: app-testver: v3spec:containers:- name: httpimage: harbor.demo.com/web/centos:v0.3imagePullPolicy: IfNotPresentports:- name: port-test-03containerPort: 8080protocol: TCP
---
apiVersion: v1
kind: Service
metadata:labels:app: app-testname: app-testnamespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: app-testports:- name: port01port: 7071targetPort: 8080protocol: TCPtype: ClusterIP

配置网关

# cat gateway-http.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:name: app-test-getwaynamespace: test
spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- www.demo.com- www.test.com

配置虚拟服务

# cat virsr.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: app-test-virsrnamespace: test
spec:hosts:- www.test.com- www.demo.comgateways:- app-test-getwayhttp:- match:- uri:prefix: /route:- destination:host: app-testport:number: 7071

生效应用

# kubectl apply -f virsr.yaml -f gateway-http.yaml -f deply_pod_svc_centos_3pod.yaml

测试

# for i in $(seq 1 6);do elinks --dump http://www.test.com/test;doneGET testing,v0.3 hello,method is getGET testing,v0.2 hello,method is getGET testing,v0.3 hello,method is getGET testing,v0.1 hello,method is getGET testing,v0.2 hello,method is getGET testing,v0.2 hello,method is get

上面配置是三个微服务随机对外提供服务。

配置目标规则,此步为细分流量做准备。

# cat dr.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: dest-rule-testnamespace: test
spec:host: app-testtrafficPolicy:loadBalancer:simple: RANDOMsubsets:- name: v1labels:ver: v1- name: v2labels:ver: v2- name: v3labels:ver: v3# kubectl apply -f dr.yaml       

5.7.1.2 百分比流量策略发布

配置流量规则,如下:
微服务v1占10%流量、v2占20%流量、v3占70%流量。

# cat virsr.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: app-test-virsrnamespace: test
spec:hosts:- www.test.com- www.demo.comgateways:- app-test-getwayhttp:- match:- uri:prefix: /route:- destination:host: app-testport:number: 7071subset: v1weight: 10- destination:host: app-testport:number: 7071subset: v2weight: 20- destination:host: app-testport:number: 7071subset: v3weight: 70# kubectl apply -f virsr.yaml       

测试

# for i in $(seq 1 10);do elinks --dump http://www.test.com/test;doneGET testing,v0.3 hello,method is getGET testing,v0.3 hello,method is getGET testing,v0.1 hello,method is getGET testing,v0.3 hello,method is getGET testing,v0.2 hello,method is getGET testing,v0.3 hello,method is getGET testing,v0.2 hello,method is getGET testing,v0.2 hello,method is getGET testing,v0.3 hello,method is getGET testing,v0.1 hello,method is get

5.7.1.3 识别浏览器类型

配置流量规则,如下:
微服务v1提供给edge、v2提供给chrome、v3提供给其它。

# cat virsr-chrome.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: app-test-virsrnamespace: test
spec:hosts:- www.test.com- www.demo.comgateways:- app-test-getwayhttp:- name: test1match:- headers:User-Agent:regex: ".*Edg.*"route:- destination:host: app-testport:number: 7071subset: v1- name: test2match:- headers:User-Agent:regex: ".*Chrome.*"route:- destination:host: app-testport:number: 7071subset: v2- name: test3route:- destination:host: app-testport:number: 7071subset: v3

测试
在这里插入图片描述

5.7.1.4 识别header信息

配置流量规则,如下:
hearder中有信息“X-Guo-1: abc1”时由微服务v1提供服务,并添加hearder信息x-version: v1。
hearder中有信息“X-Guo-2: abc2”时由微服务v2提供服务,并添加hearder信息x-version: v2。
hearder中有信息“X-Guo-3: abc3”时由微服务v3提供服务,并添加hearder信息x-version: v3。

# cat virsr-header.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: app-test-virsrnamespace: test
spec:hosts:- www.test.com- www.demo.comgateways:- app-test-getwayhttp:- name: test1match:- headers:X-Guo-1:exact: abc1route:- destination:host: app-testport:number: 7071subset: v1headers:response:add:x-version: "v1"          - name: test2match:- headers:X-Guo-2:exact: abc2route:- destination:host: app-testport:number: 7071subset: v2headers:response:add:x-version: "v2"          - name: test3match:- headers:X-Guo-3:exact: abc3route:- destination:host: app-testport:number: 7071subset: v3headers:response:add:x-version: "v3"        

测试

# curl -i -H "X-Guo-1: abc1" -XGET 'http://www.test.com/test'
HTTP/1.1 200 OK
date: Wed, 07 Jun 2023 15:39:15 GMT
content-length: 37
content-type: text/plain; charset=utf-8
x-envoy-upstream-service-time: 5
server: istio-envoy
x-version: v1GET     testing,v0.1
hello,method is get# curl -i -H "X-Guo-2: abc2" -XGET 'http://www.test.com/test'
HTTP/1.1 200 OK
date: Wed, 07 Jun 2023 15:39:20 GMT
content-length: 37
content-type: text/plain; charset=utf-8
x-envoy-upstream-service-time: 2
server: istio-envoy
x-version: v2GET     testing,v0.2
hello,method is get# curl -i -H "X-Guo-3: abc3" -XGET 'http://www.test.com/test'
HTTP/1.1 200 OK
date: Wed, 07 Jun 2023 15:39:24 GMT
content-length: 37
content-type: text/plain; charset=utf-8
x-envoy-upstream-service-time: 3
server: istio-envoy
x-version: v3GET     testing,v0.3
hello,method is get

5.7.2 CI/CD测试(AB部署)

本节是前面3.3节后续,部署到k8s上面。

升级docker-in-docker所需镜像,让它可以访问k8s,以便可以部署应用。

5.7.2.1 Ingress配置http/https

demo.test.io由app-test-1提供服务,模拟测试环境,由开发人员自动发布。
www.test.io由app-test-2提供服务,模拟生产环境,由管理员通过OA流程发布。
两者是同一个镜像,但发布条件和环境不同。

查看ingress网关地址

# kubectl get svc -A | grep LoadBalancer
istio-system     istio-ingressgateway           LoadBalancer   10.10.217.255   192.168.3.181   15021:30721/TCP,80:30406/TCP,443:31152/TCP,31400:30352/TCP,15443:30154/TCP   2d21h
nginx-ingress    nginx-ingress                  LoadBalancer   10.10.122.65    192.168.3.180   80:31582/TCP,443:32381/TCP                                                   4d8h

以istio为例

配置解析

# nslookup demo.test.io 192.168.3.250
Server:         192.168.3.250
Address:        192.168.3.250#53Name:   demo.test.io
Address: 192.168.3.181# nslookup www.test.io 192.168.3.250
Server:         192.168.3.250
Address:        192.168.3.250#53Name:   www.test.io
Address: 192.168.3.181

参照5.5.3.4,配置如下。

# kubectl config get-contexts 
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   test# kubectl  -n istio-system create secret tls web-ssl --cert=./web.pem --key=./web-key.pem# cat istio-test.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:name: app-test-getway-demonamespace: test
spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- demo.test.io- www.test.iotls:httpsRedirect: true # sends 301 redirect for http requests- port:number: 443name: https-443protocol: HTTPShosts:- demo.test.io- www.test.iotls:mode: SIMPLEcredentialName: web-ssl---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: app-test-demonamespace: test
spec:hosts:- demo.test.iogateways:- app-test-getway-demohttp:- match:- uri:prefix: /route:- destination:host: app-test-1port:number: 7071
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: app-test-wwwnamespace: test
spec:hosts:- www.test.iogateways:- app-test-getway-demohttp:- match:- uri:prefix: /route:- destination:host: app-test-2port:number: 7071

5.7.2.2 制作gitlab-ci

stages/任务说明
build/job1编译go源码为二进制文件
push_image/job2将job1生成的应用打包上镜像,并push到私有仓库
test/job3开发人员push时触发CI/CD。
将微服务镜像部署在测试环境,若deploy已存在则更新它,若不存在则创建它
deploy/job4OA流触发CI/CD。
将微服务镜像部署在正式环境,若deploy已存在则更新它,若不存在则创建它

.gitlab-ci.yml文件详细如下

#全局变量赋值
variables:image_name: "busybox"#image_name: "centos"image_ver: "v0.1.4"#定义stages
stages:- build- push_image- test- deploy#job1:编译go源码为二进制文件
#局部变量Is_Run默认值为yes,则在push时会执行此任务。
job1:variables:Is_Run: "yes"stage: buildscript:- echo "build the code..."- export GOROOT=/usr/local/go- export PATH=$PATH:/usr/local/go/bin- export GOPATH=/opt- export GO115MODULE=on- export GOOS=linux- export GOARCH=amd64- export GOPROXY="https://goproxy.cn,direct"- go version- go mod tidy- go build -o app .- mkdir build- mv app build/- mv Dockerfile_nobuild build/Dockerfileartifacts:paths:- buildtags:- docker-in-docker-test-1rules:- if: $Is_Run == "yes"#job2的工作是将job1生成的应用打包上镜像,并push到私有仓库。
#局部变量Is_Run默认值为yes,则在push时会执行此任务。
#提示:$UserName和$PassWord是在gitlab项目定义的项目级变量,用于存放私有仓库的用户名和密码
job2:variables:Is_Run: "yes"stage: push_imageneeds:- job: job1artifacts: truescript:- echo "build image and push harbor register ..."- cd build/- ls -l- docker build -t harbor.demo.com/web/$image_name:$image_ver .- docker logout harbor.demo.com- echo $PassWord | base64 -d | docker login --username $UserName  --password-stdin harbor.demo.com- docker push harbor.demo.com/web/$image_name:$image_ver- docker rmi harbor.demo.com/web/$image_name:$image_vertags:- docker-in-docker-test-1rules:- if: $Is_Run == "yes"#job3的任务是测试应用。
#局部变量Is_Run默认值为yes,则在push时会执行此任务。通常开发过程中测试。
#script中表示,若指定的deploy资源不存,就创建它,若存在,就更新它不触发滚动更新。
job3:variables:Is_Run: "yes"deploy_svc_name: "app-test-1"namespace: "test"stage: testscript:- echo "deploy_to_k8s, $deploy_svc_name, https://demo.test.io ..."- kubectl -n $namespace get deploy $deploy_svc_name 2>/dev/null &&  if [ 0 -eq 0 ]; then containers_name=`kubectl get deployments.apps $deploy_svc_name -o jsonpath={.spec.template.spec.containers[0].name}`; updateRolly=`openssl rand -hex 8`; test='{"spec":{"template":{"spec":{"containers":[{"name":"'$containers_name'","image":"harbor.demo.com/web/'$image_name:$image_ver'","imagePullPolicy":"Always","env":[{"name":"rollingUpdate","value":"'$updateRolly'"}]}]}}}}';   kubectl -n $namespace  patch deployment $deploy_svc_name --patch ''$test''; fi- kubectl -n $namespace get deploy $deploy_svc_name 2>/dev/null ||  if [ 0 -eq 0 ]; then kubectl -n $namespace create deployment $deploy_svc_name --image=harbor.demo.com/web/$image_name:$image_ver --port=8080 --replicas=1 ;   kubectl -n $namespace create service clusterip $deploy_svc_name --tcp=7071:8080;fitags:- docker-in-docker-test-1rules:- if: $Is_Run == "yes"#job4的任务用于发布
#局部变量Is_Run默认值为no,则在push时不会执行此任务,执行条件为:$Is_Run == "deploy"。
#需通过webhook方式执行此任务。通常用于在OA工作流中供领导审批是否正式发布此应用。
#script中表示,若指定的deploy资源不存,就创建它,若存在,就更新它不触发滚动更新。
job4:variables:Is_Run: "no"deploy_svc_name: "app-test-2"namespace: "test"stage: deployscript:- echo "deploy_to_k8s, $deploy_svc_name, https://www.test.io ..."- kubectl -n $namespace get deploy $deploy_svc_name 2>/dev/null &&  if [ 0 -eq 0 ]; then containers_name=`kubectl get deployments.apps $deploy_svc_name -o jsonpath={.spec.template.spec.containers[0].name}`; updateRolly=`openssl rand -hex 8`; test='{"spec":{"template":{"spec":{"containers":[{"name":"'$containers_name'","image":"harbor.demo.com/web/'$image_name:$image_ver'","imagePullPolicy":"Always","env":[{"name":"rollingUpdate","value":"'$updateRolly'"}]}]}}}}';   kubectl -n $namespace  patch deployment $deploy_svc_name --patch ''$test''; fi- kubectl -n $namespace get deploy $deploy_svc_name 2>/dev/null ||  if [ 0 -eq 0 ]; then kubectl -n $namespace create deployment $deploy_svc_name --image=harbor.demo.com/web/$image_name:$image_ver --port=8080 --replicas=1 ;   kubectl -n $namespace create service clusterip $deploy_svc_name --tcp=7071:8080;fitags:- docker-in-docker-test-1rules:- if: $Is_Run == "deploy"

5.7.2.3 开发人员push发布到测试环境

push源码

git add *
git commit -m "test-1"
git push http://git.demo.com/guofs/cicdtest.git main

查看

# curl https://demo.test.io/test
GET     testing v0.1.6
hello,method is get

5.7.2.4 OA流程调用webhook发布到正式环境

测试环境通过后,可通过OA流程调用webhook发布到正式环境。
用于领导申批是否正式发布。

curl -X POST \--fail \-F token=glptt-938d9966afdc10180540a775d6e5e399fcd2cea0 \-F ref=main \-F "variables[Is_Run]=deploy" \-F "variables[deploy_svc_name]=app-test-2" \http://git.demo.com/api/v4/projects/8/trigger/pipeline

查看

# curl -Xhttps://www.test.io/test
GET     testing v0.1.6
hello,method is get

5.7.3 滚动更新

K8S默认配置滚动更新,默认策略如下

  replicas: 1revisionHistoryLimit: 10strategy:rollingUpdate:maxSurge: 25%maxUnavailable: 25%type: RollingUpdate

触发滚动升级的条件

1。pod模板中镜像的策略必须是"imagePullPolicy: Always"。
2。Deployment中的pod模板中的配置发生变化。

发生滚动升级后,有如下变化

1。更新后,pod的ID发生变化
2。产生一个新的replicaset.apps对像

结合5.7.2办法,用如下go代码更新并产生新镜像。

package mainimport ("fmt""log""net/http"
)func handler_url(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "%v\t%v\n", r.Method, "testing v0.1.1")if r.Method == "GET" {fmt.Fprintf(w, "hello,method is %v\n", "get")}if r.Method == "POST" {fmt.Fprintf(w, "hello,method is %v\n", "post")}if r.Method == "PUT" {fmt.Fprintf(w, "%v\n", "post")}}func main() {http.HandleFunc("/test", handler_url)err := http.ListenAndServe(":8080", nil) //启动http服务器if err != nil {log.Fatalln(err)}
}

更改Fprintf输出后依次v0.1、v0.2、v0.3、v0.4镜像。

查看deployt和rs

# kubectl get deploy,rs  -o wide
NAME                         READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                             SELECTOR
deployment.apps/app-test-1   1/1     1            1           8m45s   busybox      harbor.demo.com/web/busybox:v0.4   app=app-test-1NAME                                    DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES                             SELECTOR
replicaset.apps/app-test-1-6467784f89   0         0         0       5m55s   busybox      harbor.demo.com/web/busybox:v0.2   app=app-test-1,pod-template-hash=6467784f89
replicaset.apps/app-test-1-7b5f4489d4   0         0         0       3m42s   busybox      harbor.demo.com/web/busybox:v0.3   app=app-test-1,pod-template-hash=7b5f4489d4
replicaset.apps/app-test-1-7c997956fc   1         1         1       98s     busybox      harbor.demo.com/web/busybox:v0.4   app=app-test-1,pod-template-hash=7c997956fc
replicaset.apps/app-test-1-86cdb4866c   0         0         0       8m45s   busybox      harbor.demo.com/web/busybox:v0.1   app=app-test-1,pod-template-hash=86cdb4866c

查看滚动历史

# kubectl rollout history deployment app-test-1 
deployment.apps/app-test-1 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
4         <none>

当前版本是v4.

# curl https://demo.test.io/test
GET     testing v0.4
hello,method is get

回滚到v2

kubectl rollout undo deployment app-test-1 --to-revision=2

查看回滚效果

# curl https://demo.test.io/test
GET     testing v0.2
hello,method is get

查看回滚后deployt和rs

# kubectl get deploy,rs  -o wide
NAME                         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                             SELECTOR
deployment.apps/app-test-1   1/1     1            1           14m   busybox      harbor.demo.com/web/busybox:v0.2   app=app-test-1NAME                                    DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES                             SELECTOR
replicaset.apps/app-test-1-6467784f89   1         1         1       11m     busybox      harbor.demo.com/web/busybox:v0.2   app=app-test-1,pod-template-hash=6467784f89
replicaset.apps/app-test-1-7b5f4489d4   0         0         0       9m31s   busybox      harbor.demo.com/web/busybox:v0.3   app=app-test-1,pod-template-hash=7b5f4489d4
replicaset.apps/app-test-1-7c997956fc   0         0         0       7m27s   busybox      harbor.demo.com/web/busybox:v0.4   app=app-test-1,pod-template-hash=7c997956fc
replicaset.apps/app-test-1-86cdb4866c   0         0         0       14m     busybox      harbor.demo.com/web/busybox:v0.1   app=app-test-1,pod-template-hash=86cdb4866c

5.7.4 HPA弹性计算

使用如下go代码创建微服务镜像harbor.demo.com/web/busybox:v0.6

package mainimport ("fmt""log""math""net/http"
)func handler_url(w http.ResponseWriter, r *http.Request) {var num = 3.1425926var i = 0for ; i < 10000000; i++ {num += math.Sqrt(num)}fmt.Fprintf(w, "num=%v,i=%v\n", num, i)fmt.Fprintf(w, "%v\t%v\n", r.Method, "testing v0.5")if r.Method == "GET" {fmt.Fprintf(w, "hello,method is %v\n", "get")}if r.Method == "POST" {fmt.Fprintf(w, "hello,method is %v\n", "post")}if r.Method == "PUT" {fmt.Fprintf(w, "%v\n", "post")}}func main() {http.HandleFunc("/test", handler_url)err := http.ListenAndServe(":8080", nil) //启动http服务器if err != nil {log.Fatalln(err)}
}

创建pod模板

# cat pod.yaml
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testreplicas: 2template:metadata:name: app-testnamespace: testlabels:app: app-testspec:containers:- name: httpimage: harbor.demo.com/web/busybox:v0.6imagePullPolicy: IfNotPresentports:- name: port-test-01containerPort: 8080protocol: TCPresources:limits:cpu: 80mrequests:cpu: 20m
---apiVersion: v1
kind: Service
metadata:labels:app: app-testname: app-testnamespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: app-testports:- name: port01port: 7071targetPort: 8080protocol: TCPtype: ClusterIP

创建ingress配置

# cat istio-test.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:name: app-test-getway-hpanamespace: test
spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- www.test.comtls:httpsRedirect: true- port:number: 443name: https-443protocol: HTTPShosts:- www.test.comtls:mode: SIMPLEcredentialName: web-ssl        ---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: app-test-hpanamespace: test
spec:hosts:- www.test.comgateways:- app-test-getway-hpahttp:- match:- uri:prefix: /route:- destination:host: app-testport:number: 7071

创建hpa

kubectl autoscale deployment app-test --cpu-percent=50 --min=1 --max=10

测试前

# kubectl get hpa
NAME       REFERENCE             TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
app-test   Deployment/app-test   16%/50%   1         10        1          6m21s

测试

# for i in $(seq 1 200);do curl https://www.test.com/test;done
num=2.499998060324e+13,i=10000000
GET     testing v0.5
hello,method is get
num=2.499998060324e+13,i=10000000
GET     testing v0.5
hello,method is get
num=2.499998060324e+13,i=10000000
GET     testing v0.5
hello,method is get
num=2.499998060324e+13,i=10000000
GET     testing v0.5
hello,method is get
...

查看hpa,可以看到pod副本扩容效果增到9。

# kubectl get hpa
NAME       REFERENCE             TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
app-test   Deployment/app-test   48%/50%   1         10        9          9m9s# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
app-test-748d6b44bb-5vwnl   2/2     Running   0          2m
app-test-748d6b44bb-78llx   2/2     Running   0          3m30s
app-test-748d6b44bb-8b5sn   2/2     Running   0          95m
app-test-748d6b44bb-8zqzk   2/2     Running   0          3m30s
app-test-748d6b44bb-glgvc   2/2     Running   0          3m15s
app-test-748d6b44bb-r77cj   2/2     Running   0          45s
app-test-748d6b44bb-w8z92   2/2     Running   0          2m
app-test-748d6b44bb-xwqct   2/2     Running   0          3m30s
app-test-748d6b44bb-zrrqn   2/2     Running   0          3m15s

停止测试

# kubectl get hpa
NAME       REFERENCE             TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
app-test   Deployment/app-test   8%/50%   1         10        1          24m# kubectl top pod 
NAME                        CPU(cores)   MEMORY(bytes)   
app-test-748d6b44bb-8b5sn   4m           61Mi            

需等待一些时间可以看到缩容效果。

六、第三方镜像部署

6.1 数据库mysql配置(有状态部署)

采用有状态部署mysql,mysql对主机名和数据库存储目录要求

# cat mysql.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:name: app-test-mysqlnamespace: test
spec:serviceName: app-test-mysqlselector:matchLabels:app: app-test-mysqlreplicas: 1template:metadata:name: app-test-mysqlnamespace: testlabels:app: app-test-mysqlspec:containers:- name: mysqlimage: harbor.demo.com/app/mysql:latest#image: harbor.demo.com/web/busybox:v0.1imagePullPolicy: IfNotPresentvolumeMounts:- name: mysql-datamountPath: /var/lib/mysqlports:- name: port-test-01containerPort: 3306protocol: TCPenv:- name: MYSQL_ROOT_PASSWORDvalue: 12qwaszxvolumeClaimTemplates:               - metadata:name: mysql-dataspec:accessModes: [ "ReadWriteOnce" ]storageClassName: csi-rbd-scresources:requests:storage: 5Gi            
---apiVersion: v1
kind: Service
metadata:labels:app: app-test-mysqlname: app-test-mysqlnamespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: app-test-mysqlports:- name: port01port: 3306targetPort: 3306protocol: TCPtype: ClusterIP# kubectl apply -f mysql.yaml 

测试pod(mysql client)

# cat client.yaml
apiVersion: apps/v1 
kind: Deployment 
metadata:name: app-testnamespace: test
spec:selector:matchLabels:app: app-testtemplate:metadata:name: app-testnamespace: testlabels:app: app-testspec:containers:- name: mysql-clientimage: harbor.demo.com/test/testtool:v0.2imagePullPolicy: IfNotPresent# kubectl apply -f client.yaml # kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
app-test-6b76f4f697-mzn7c   2/2     Running   0          22m
app-test-mysql-0            2/2     Running   0          22m# kubectl exec pod/app-test-6b76f4f697-mzn7c -it /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
[root@app-test-6b76f4f697-mzn7c app]# mysql -u root -h app-test-mysql.test.svc.cluster.local -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.0.33 MySQL Community Server - GPLCopyright (c) 2000, 2021, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| gfs                |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

删除pod再产生新的pod副本,数据仍然存在。

6.2 私有化部署chatgpt

七、运维层

7.1 dashboard配置

安装k8s官方提供的dashboard

# wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml -o dashboard.yaml# cat dashboard.yaml | grep image:image: kubernetesui/dashboard:v2.7.0image: kubernetesui/metrics-scraper:v1.0.8
转存到私仓,并修改镜像地址,如下# cat dashboard.yaml | grep image:image: harbor.demo.com/k8s/dashboard:v2.7.0image: harbor.demo.com/k8s/metrics-scraper:v1.0.8配置svc采用LB方式
# vi dashboard.yaml 
...
kind: Service
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
spec:ports:- port: 443targetPort: 8443selector:k8s-app: kubernetes-dashboardtype: LoadBalancer
...# kubectl apply -f dashboard.yaml 
# kubectl get all -n kubernetes-dashboard
NAME                                            READY   STATUS    RESTARTS   AGE
pod/dashboard-metrics-scraper-d97df5556-vvv9w   1/1     Running   0          16s
pod/kubernetes-dashboard-6694866798-pcttp       1/1     Running   0          16sNAME                                TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)         AGE
service/dashboard-metrics-scraper   ClusterIP      10.10.153.173   <none>          8000/TCP        17s
service/kubernetes-dashboard        LoadBalancer   10.10.186.6     192.168.3.182   443:31107/TCP   18sNAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/dashboard-metrics-scraper   1/1     1            1           17s
deployment.apps/kubernetes-dashboard        1/1     1            1           17sNAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/dashboard-metrics-scraper-d97df5556   1         1         1       17s
replicaset.apps/kubernetes-dashboard-6694866798       1         1         1       17s

添加用户

# cat admin-user.yaml
apiVersion: v1
kind: ServiceAccount
metadata:name: admin-usernamespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: admin-user
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-admin
subjects:
- kind: ServiceAccountname: admin-usernamespace: kubernetes-dashboard# kubectl apply -f admin-user.yaml# kubectl -n kubernetes-dashboard create token admin-user
eyJhbGciOiJSUzI1NiIsImtpZCI6IjlUNmROZTZZSEJ4WEJIell2OG5IQS1oTGVLYjJWRU9QRlhzUFBmdlVONU0ifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjg2NTQ3MTE3LCJpYXQiOjE2ODY1NDM1MTcsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJhZG1pbi11c2VyIiwidWlkIjoiNjk1MWFlODktODYwMi00NzAzLTk3NzYtMmNhNmU0OTJlZjQ2In19LCJuYmYiOjE2ODY1NDM1MTcsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDphZG1pbi11c2VyIn0.j9XHrznphuwv56hcSGRlcOxvzuGGbKEdPZB1r5jc84kNICp2sTwXvr71d6wdYtzGxjODZ81kTqVqRQUcUKi0Uh8OWjxWcspNJIWk0y6_Eub823YWzkusktb7NdqCb6BYIyX79V4iFUQaVjp9BlEXSZ6vnuJhwvEonumDrIo0JtUF8PT1ZV3319kajFTZMWza-QHRMFOjGC74YleMd-7gDA-aimoxjPQIVfIWF2PhssLj38Ci-KZddxOE1yE42QFOmPozOzCT348ZEJEO1lhDC4trnK2TTU8jb1sM7RyPKuvyY0fbimqNi6iGL-aqCaQT6_nWDvxkVycapJ3KAwz2Zw

访问

# nslookup dashboard.demo.com
Server:         192.168.3.250
Address:        192.168.3.250#53Name:   dashboard.demo.com
Address: 192.168.3.182

https://dashboard.demo.com
在这里插入图片描述

7.2 rancher

https://github.com/rancher/rancher

常用的k8s容器编排工具如openshift和rancher.
本文以rancher为例。rancher可以同时管理多个k8s集群。

rancher版本
latest 当前最新版,v2.7.3
stable 当前稳定版,v2.6.12

7.2.1 rancher节点安装

安装docker

yum -y install yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum -y install docker-ce docker-ce-cli containerd.io
systemctl enable docker containerd
systemctl start docker containerd

rancher镜像拉取(比较大,建议拉取后转存私仓)

# docker pull rancher/rancher:latest

创建rancher节点目录

mkdir -p /opt/racher

7.2.1.1 rancher-web被访问时的证书配置

将域名证书复制到/opt/racher/ca将证书等改名,如下:
ca.pem ----> cacerts.pem
web-key.pem  ---> key.pem
web.pem ---> cert.pem# tree /opt/rancher/ca
/opt/rancher/ca
├── cacerts.pem
├── cert.pem
└── key.pem

7.2.1.2 私仓配置

# cat /opt/rancher/registries.yaml 
mirrors:harbor.demo.com:endpoint:- "harbor.demo.com"
configs:"harbor.demo.com":auth:username: adminpassword: 12qwaszx+pptls:ca_file: /opt/harbor/ca.crtcert_file: /opt/harbor/harbor.demo.com.certkey_file: /opt/harbor/harbor.demo.com.key
其中的 /opt/harbor/ 目录是rancher节点运行时其容器内部的目录。私仓库被访问时需使用的证书
# tree /opt/rancher/ca_harbor/
/opt/rancher/ca_harbor/
├── ca.crt
├── harbor.demo.com.cert
└── harbor.demo.com.key
在启动rancher时,需将 /opt/rancher/ca_harbor/ 映射到容器的 /opt/harbor/ 目录(在registries-https.yaml中已指定该目录)

7.2.1.3 安装rancher节点

# docker run -d -it -p 80:80 -p 443:443  --name rancher --privileged=true --restart=unless-stopped \
-v /opt/rancher/k8s:/var/lib/rancher \
-v /opt/rancher/ca:/etc/rancher/ssl \
-e SSL_CERT_DIR="/etc/rancher/ssl" \
-e CATTLE_SYSTEM_DEFAULT_REGISTRY=harbor.demo.com \
-v /opt/rancher/registries.yaml:/etc/rancher/k3s/registries.yaml \
-v /opt/rancher/ca_harbor:/opt/harbor \
rancher/rancher:latest

查看启动日志

# docker logs rancher -f

7.2.1.4 访问rancher web

# nslookup rancher.demo.com
Server:         192.168.3.250
Address:        192.168.3.250#53Name:   rancher.demo.com
Address: 10.2.20.151

访问https://rancher.demo.com
在这里插入图片描述

查看默认admin用户密码

# docker exec -it rancher kubectl get secret --namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}{{"\n"}}'

若忘记密码,则重设密码

# docker exec -it rancher reset-password

7.2.2 添加外部k8s集群

在这里插入图片描述
在这里插入图片描述

# curl --insecure -sfL https://rancher.demo.com/v3/import/rndjzbgwn78v6v6dx28dlngn7r7qrlwv4b949c47567ltjz7g76tqn_c-m-68r9m4vz.yaml  -o rancher.yaml
# cat rancher.yaml | grep image:image: rancher/rancher-agent:v2.7.3
改为私仓地址
# cat rancher.yaml | grep image:image: harbor.demo.com/rancher/rancher-agent:v2.7.3安装
# kubectl apply -f rancher.yaml 查看
# kubectl -n cattle-system get all
NAME                                        READY   STATUS              RESTARTS   AGE
pod/cattle-cluster-agent-5cb7bb7b9b-kc5fn   0/1     ContainerCreating   0          27sNAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/cattle-cluster-agent   ClusterIP   10.10.104.246   <none>        80/TCP,443/TCP   27sNAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cattle-cluster-agent   0/1     1            0           28sNAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/cattle-cluster-agent-5cb7bb7b9b   1         1         0       28s

在这里插入图片描述

在这里插入图片描述
查看某个pod
在这里插入图片描述

7.2.3 新增k8s集群

使用rancher建立新的k8s集群较简单,在目标节点上直接运行相应命令即可。
在这里插入图片描述
在这里插入图片描述

7.3 prometheus/grafana

https://github.com/prometheus/prometheus/

Prometheus是一个开源的系统监控和报警系统,是当前一套非常流行的开源监控和报警系统之一,CNCF托管的项目,在kubernetes容器管理系统中,通常会搭配prometheus进行监控,Prometheus性能足够支撑上万台规模的集群。
在这里插入图片描述
prometheus显著特点
1。多维数据模型(时间序列由metrics指标名字和设置key/value键/值的labels构成),高效的存储
2。灵活的查询语言(PromQL)
3。采用http协议,使用pull模式,拉取数据
4。通过中间网关支持推送。
5。丰富多样的Metrics采样器exporter。
6。与Grafana完美结合,由Grafana提供数据可视化能力。

Grafana 是一个用于可视化大型测量数据的开源系统,它的功能非常强大,界面也非常漂亮,使用它可以创建自定义的控制面板,你可以在面板中配置要显示的数据和显示方式,有大量第三方可视插件可使用。

Prometheus/Grafana支持多种方式安装,如源码、二进制、镜像等方式,都比较简单。

本文以kube-prometheus方式在k8s上安装Prometheus/Grafana.
官方安装文档:https://prometheus-operator.dev/docs/prologue/quick-start/ ​
安装要求:https://github.com/prometheus-operator/kube-prometheus#compatibility ​
官方Github地址:https://github.com/prometheus-operator/kube-prometheus

7.3.1 kube-prometheus安装

下载

# git clone https://github.com/coreos/kube-prometheus.git
# cd kube-prometheus/manifests

查看所需镜像,并转存到私仓,同时修改清单文件中的镜像地址改为私仓

# find ./ | xargs grep image:
# cat prometheusOperator-deployment.yaml | grep prometheus-config-reloader- --prometheus-config-reloader=quay.io/prometheus-operator/prometheus-config-reloader:v0.65.2

更改prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml

# cat prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:labels:app.kubernetes.io/component: metrics-adapterapp.kubernetes.io/name: prometheus-adapterapp.kubernetes.io/part-of: kube-prometheusapp.kubernetes.io/version: 0.10.0rbac.authorization.k8s.io/aggregate-to-admin: "true"rbac.authorization.k8s.io/aggregate-to-edit: "true"rbac.authorization.k8s.io/aggregate-to-view: "true"name: system:aggregated-metrics-reader#namespace: monitoring
rules:
- apiGroups:- metrics.k8s.ioresources:- services- endpoints- pods- nodesverbs:- get- list- watch提示:
本配置定义的资源在安装metrics-reader时已提供,此时只需更新一下配置即可。

更改prometheus-clusterRole.yaml

下面的更改,参照istio中提供的prometheus配置
# cat prometheus-clusterRole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:labels:app.kubernetes.io/component: prometheusapp.kubernetes.io/instance: k8sapp.kubernetes.io/name: prometheusapp.kubernetes.io/part-of: kube-prometheusapp.kubernetes.io/version: 2.44.0name: prometheus-k8s
rules:- apiGroups:- ""resources:- nodes- nodes/proxy- nodes/metrics- services- endpoints- pods- ingresses- configmapsverbs:- get- list- watch- apiGroups:- "extensions"- "networking.k8s.io"resources:- ingresses/status- ingressesverbs:- get- list- watch- nonResourceURLs:- "/metrics"verbs:- get说明:
若采用kube-promethenus提供的配置,则在创建ServiceMonitor时不会被prometheus识别。

安装

# kubectl create -f setup/
# kubectl apply -f ./prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml
# rm -f prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml
# kubectl create -f ./
查看svc
# kubectl -n monitoring get svc
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
alertmanager-main       ClusterIP   10.10.251.51    <none>        9093/TCP,8080/TCP            7m18s
alertmanager-operated   ClusterIP   None            <none>        9093/TCP,9094/TCP,9094/UDP   6m51s
blackbox-exporter       ClusterIP   10.10.195.115   <none>        9115/TCP,19115/TCP           7m17s
grafana                 ClusterIP   10.10.121.183   <none>        3000/TCP                     7m13s
kube-state-metrics      ClusterIP   None            <none>        8443/TCP,9443/TCP            7m12s
node-exporter           ClusterIP   None            <none>        9100/TCP                     7m10s
prometheus-k8s          ClusterIP   10.10.230.211   <none>        9090/TCP,8080/TCP            7m9s
prometheus-operated     ClusterIP   None            <none>        9090/TCP                     6m48s
prometheus-operator     ClusterIP   None            <none>        8443/TCP                     7m8s

域名解析

prometheus.demo.com 192.168.3.180
grafana.demo.com 192.168.3.180
alert.demo.com 192.168.3.180

对外开放服务

# cat open-ui.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: monitor-prometheusnamespace: monitoring
spec:ingressClassName: nginxrules:- host: prometheus.demo.comhttp:paths:- backend:service:name: prometheus-k8sport:number: 9090path: /pathType: Prefix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: monitor-grafananamespace: monitoring
spec:ingressClassName: nginxrules:- host: grafana.demo.comhttp:paths:- backend:service:name: grafanaport:number: 3000path: /pathType: Prefix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: monitor-alertnamespace: monitoring
spec:ingressClassName: nginxrules:- host: alert.demo.comhttp:paths:- backend:service:name: alertmanager-mainport:number: 9093path: /pathType: Prefix# kubectl apply -f open-ui.yaml

访问
http://grafana.demo.com (默认用户名admin,密码admin)

kube-prometheus已配置一些模板,如:
在这里插入图片描述
可以从https://grafana.com/grafana/dashboards/找到所需模板,如14518模板
在这里插入图片描述

7.3.2 应用配置样例

ServiceMonitor 自定义资源(CRD)能够声明如何监控一组动态服务的定义。它使用标签选择定义一组需要被监控的服务。这样就允许组织引入如何暴露 metrics 的规定,只要符合这些规定新服务就会被发现列入监控,而不需要重新配置系统。

Prometheus就是通过ServiceMonitor提供的metrics数据接口把我们数据pull过来的。ServiceMonitor 通过label标签和对应的 endpoint 和 svc 进行关联。

查看kube-prometheus自带的ServiceMonitor

# kubectl -n monitoring get ServiceMonitor
NAME                      AGE
alertmanager-main         96m
app-test-ext-test         91s
blackbox-exporter         96m
coredns                   96m
grafana                   96m
kube-apiserver            96m
kube-controller-manager   96m
kube-scheduler            96m
kube-state-metrics        96m
kubelet                   96m
node-exporter             96m
prometheus-k8s            96m
prometheus-operator       96m

7.3.2.1 ceph Metrics(集群外部ceph)

启动ceph exporter的监听端口

# ceph mgr module enable prometheus
# ss -lntp | grep mgr
LISTEN 0      128       10.2.20.90:6802      0.0.0.0:*    users:(("ceph-mgr",pid=1108,fd=27))
LISTEN 0      128       10.2.20.90:6803      0.0.0.0:*    users:(("ceph-mgr",pid=1108,fd=28))
LISTEN 0      5                  *:8443            *:*    users:(("ceph-mgr",pid=1108,fd=47))
LISTEN 0      5                  *:9283            *:*    users:(("ceph-mgr",pid=1108,fd=38))    //其中9283是ceph exporter的监听端口查看
http://10.2.20.90:9283/metrics

创建svc和endpoints

# cat ext-ceph.yaml 
apiVersion: v1
kind: Service
metadata:labels:app: app-test-ext-cephname: app-test-ext-cephnamespace: test
spec:ports:- name: ceph-metricsport: 9283targetPort: 9283protocol: TCP---
apiVersion: v1
kind: Endpoints
metadata:name: app-test-ext-cephnamespace: testlabels:app: app-test-ext-ceph
subsets:
- addresses:- ip: 10.2.20.90ports:- name: ceph-metricsport: 9283

创建ServiceMonitor

# cat sm.yaml 
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:labels:app: app-test-ext-cephname: app-test-ext-cephnamespace: test
spec:jobLabel: app-test-ext-cephendpoints:- interval: 10sport: ceph-metricspath: /metricsscheme: httpselector:matchLabels:app: app-test-ext-cephnamespaceSelector:matchNames:- test
# kubectl apply -f ext-ceph.yaml -f sm.yaml 

在prometheus中可以发现添加的ServiceMonitor已被识别。
在这里插入图片描述

在grafana添加ceph模板2842,例如:
在这里插入图片描述

7.3.2.2 istio边车容器metrics(自动发现)

istio的边车容器默认要用15020作为metrics采集端口。

配置svc对像

# cat sv.yaml 
apiVersion: v1
kind: Service
metadata:labels:sidecar-metrice: testname: app-test-15020namespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:security.istio.io/tlsMode: istio	//匹对启用边车代理的容器。ports:- name: istio-sidecarport: 15020targetPort: 15020protocol: TCPtype: ClusterIP

创建sm

# cat sm-test.yaml 
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:labels:app: app-test-smname: app-test-sm-istio-sidecarnamespace: test
spec:jobLabel: app.kubernetes.io/nameendpoints:- interval: 5sport: istio-sidecarpath: /metricsscheme: httpselector:matchLabels:sidecar-metrice: test		//匹对带有“sidecar-metrice: test”标签的svc/endpointnamespaceSelector:matchNames:- test     

在prometheus中可以发现添加的ServiceMonitor已被识别。

7.3.2.3 nginx ingress Metrics

修改nginx ingress的pod模板,打开metrics。

# vi ingress/nginx/kubernetes-ingress-main/deployments/deployment/nginx-ingress.yaml
...ports:- name: httpcontainerPort: 80- name: httpscontainerPort: 443- name: readiness-portcontainerPort: 8081- name: prometheuscontainerPort: 9113
...args:- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config#- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret#- -include-year#- -enable-cert-manager#- -enable-external-dns#- -v=3 # Enables extensive logging. Useful for troubleshooting.#- -report-ingress-status#- -external-service=nginx-ingress- -enable-prometheus-metrics       #取消注解。 
...# kubectl apply -f ingress/nginx/kubernetes-ingress-main/deployments/deployment/nginx-ingress.yaml

创建针对metrics的服务

# cat sv.yaml 
apiVersion: v1
kind: Service
metadata:labels:nginx-metrice: testname: app-test-9113namespace: nginx-ingress
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: nginx-ingressports:- name: prometheusport: 9113targetPort: 9113protocol: TCPtype: ClusterIP

创建sm

# cat sm.yaml 
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:labels:app: app-test-nginx-ingressname: app-test-nginx-ingressnamespace: nginx-ingress
spec:jobLabel: app.kubernetes.io/nameendpoints:- interval: 10sport: prometheuspath: /metricsscheme: httpselector:matchLabels:nginx-metrice: testnamespaceSelector:matchNames:- nginx-ingress

则在prometheus中可以发现添加的ServiceMonitor已被识别。
在这里插入图片描述

在grafana中添加模板即可,如下
在这里插入图片描述

7.3.2.4 mysql Metrics

拉取mysqld-exporter并转私仓harbor.demo.com/exporter/mysqld-exporter:latest

# docker pull bitnami/mysqld-exporter

开启数据库,采用有状态部署方式

# cat mysql.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:name: app-test-mysqlnamespace: test
spec:serviceName: app-test-mysqlselector:matchLabels:app: app-test-mysqlreplicas: 1template:metadata:name: app-test-mysqlnamespace: testlabels:app: app-test-mysqlspec:containers:- name: mysqlimage: harbor.demo.com/app/mysql:latestimagePullPolicy: IfNotPresentvolumeMounts:- name: mysql-datamountPath: /var/lib/mysqlports:- name: port-test-01containerPort: 3306protocol: TCPenv:- name: MYSQL_ROOT_PASSWORDvalue: abc123456args:- --character-set-server=gbkvolumeClaimTemplates:               - metadata:name: mysql-dataspec:accessModes: [ "ReadWriteOnce" ]storageClassName: csi-rbd-scresources:requests:storage: 5Gi            
---apiVersion: v1
kind: Service
metadata:labels:app: app-test-mysqlname: app-test-mysqlnamespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: app-test-mysqlports:- name: port01port: 3306targetPort: 3306protocol: TCPtype: ClusterIP

mysql库创建相应用户并赋权

use mysql;
create user 'admin'@'%' identified with mysql_native_password  by '123456';
grant ALL on *.* to 'admin'@'%' with grant option;
flush privileges;

开启exporter,默认采用9104端口来收集metrics

# cat exporter.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: app-test-mysql-exporternamespace: test
spec:selector:matchLabels:app: app-test-mysql-exporterreplicas: 1template:metadata:name: app-test-mysql-exporternamespace: testlabels:app: app-test-mysql-exporterspec:containers:- name: mysqld-exporterimage: harbor.demo.com/exporter/mysqld-exporter:latestimagePullPolicy: IfNotPresentports:- name: port-test-02containerPort: 9104protocol: TCPenv:- name: DATA_SOURCE_NAMEvalue: 'admin:123456@(app-test-mysql.test.svc:3306)/'
---apiVersion: v1
kind: Service
metadata:labels:app: app-test-mysql-exportername: app-test-mysql-exporternamespace: test
spec:sessionAffinity: ClientIPsessionAffinityConfig:clientIP:timeoutSeconds: 10800selector:app: app-test-mysql-exporterports:- name: mysql-exporterport: 9104targetPort: 9104protocol: TCPtype: ClusterIP

创建sm

# cat sm.yaml 
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:labels:app: app-test-mysql-exportername: app-test-mysql-exporternamespace: test
spec:jobLabel: app.kubernetes.io/nameendpoints:- interval: 10sport: mysql-exporterpath: /metricsscheme: httpselector:matchLabels:app: app-test-mysql-exporternamespaceSelector:matchNames:- test 

则在prometheus中可以发现添加的ServiceMonitor已被识别。
在grafana中添加模板即可,如:在这里插入图片描述

7.3.3 配置rule和告警

7.3.3.1 配置rule

查看kube-prometheus安装时提供的规则

# kubectl -n monitoring get prometheusrules
NAME                              AGE
alertmanager-main-rules           22h
grafana-rules                     22h
kube-prometheus-rules             22h
kube-state-metrics-rules          22h
kubernetes-monitoring-rules       22h
node-exporter-rules               22h
prometheus-k8s-prometheus-rules   22h
prometheus-operator-rules         22h

为方便查看测试效果,可删除默认安装的规则.

添加测试规则

# cat rule1.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:labels:prometheus: k8srole: alert-rulesname: rule-test-1namespace: monitoring
spec:groups:- name: rule-test-1rules:- alert: InstanceDownexpr: up == 0for: 1mlabels:severity: warningannotations:summary: "服务 {{ $labels.instance }} 下线了"description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minutes."# cat rule2.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:labels:prometheus: k8srole: alert-rulesname: rule-test-2namespace: monitoring
spec:groups:- name: rule-test-2rules:- alert: Watchdogannotations:message: |此警报旨在确认整个警报管道功能性的。这个警报始终处于触发状态,因此它应始终在Alertmanager中触发,并始终针对各类接收器发送。expr: vector(1)labels:severity: none# kubectl create -f rule1.yaml -f rule2.yaml
# kubectl -n monitoring get prometheusrules
NAME          AGE
rule-test-1   87m
rule-test-2   32m

在这里插入图片描述

7.3.3.1 配置alert

# cat /tmp/alert.conf
global:smtp_smarthost: 'smtp.139.com:25'smtp_from: 'guofs@139.com'smtp_auth_username: 'guofs@139.com'smtp_auth_password: 'abc1239034b78612345678'smtp_require_tls: falseroute:group_by: ['alertname']group_wait: 30sgroup_interval: 5mrepeat_interval: 1hreceiver: 'default-receiver'receivers:
- name: 'default-receiver'email_configs:- to: 'guofs@163.com'inhibit_rules:
- source_match:severity: 'critical'target_match:severity: 'warning'equal: ['alertname', 'dev', 'instance']# kubectl -n monitoring create secret generic alertmanager-main --from-file=alertmanager.yaml=/tmp/alert.conf --dry-run -o yaml  |  kubectl -n=monitoring create -f -重启pod,以便配置生效。
kubectl -n monitoring delete pod alertmanager-main-0查看日志
# kubectl -n monitoring logs pod/alertmanager-main-0 -f

收到告警邮件如下
在这里插入图片描述

八、附录

针对本文所涉及的开源软件 ,csdn上面有很多优秀的网贴,针对某一个知识点讲得很深入。
我在测试时prometheus/alertmanager报警部分时,参照了如下网贴,感谢作者辛苦付出。
https://blog.csdn.net/qq_40859395/article/details/124111257
https://blog.csdn.net/zfw_666666/article/details/126870239
https://blog.csdn.net/weixin_43451568/article/details/129781576

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/32124.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WAIC2023| AIGC究竟在向善还是向恶而行?

目录 一、常见图像篡改技术二、传统篡改图像检测方法2.1、基于光源和噪声的拼接图像篡改检测方法2.2、基于马尔科夫特征的检测方法 三、基于深度学习的图像篡改检测方法3.1、基于Fisher编码和SVM模型的方法3.2、 基于局部异常特征检测的Mantra-Net方法3.2、基于HRNet的编码器—…

软件工程实践——软件测评作业

这个作业属于哪个课程2023年福大-软件工程实践W班这个作业要求在哪里作业要求这个作业的目标分析比较网络上的几个编程网站并给出评测提升自己对软件工程的理解其他参考文献《构建之法》邹欣老师的案例分析软件评分参考Bug定性的标准 文章目录 Bug定性标准第一部分 调研、评测1…

[深度学习入门案例1]基于Keras的手写数字图像识别

文章目录 一、工具与环境 二、深度学习环境的搭建 1.安装Anaconda 2.创建虚拟环境 第1步&#xff1a;打开Anaconda的命令窗口&#xff0c;即Anaconda Prompt 第2步&#xff1a;使用命令创建指定版本的python环境&#xff08;这里以py36命令环境名称举例&#xff09; 3.切换…

发布变更又快又稳?腾讯运维工程师经验首发

导读| 如何让功能缺陷修复快速上线&#xff1f;版本发出问题时怎样快速回退&#xff1f;效率提升后质量掉队&#xff1f;为解决这些常让运维工程师头疼的事情&#xff0c;本栏目特邀腾讯知名运维工程师袁旭东&#xff0c;讲述对象存储COS的发布演进过程&#xff0c;为各位开发者…

国内外人工智能AI工具网站大全(非常详细)从零基础入门到精通,看完这一篇就够了

国内外人工智能AI工具网站大全&#xff08;一键收藏&#xff0c;应有尽有&#xff09; 摘要一、AI写作工具二、AI图像工具 2.1、常用AI图像工具2.2、AI图片插画生成2.3、AI图片背景移除2.4、AI图片无损调整2.5、AI图片优化修复2.6、AI图片物体抹除 三、AI音频工具四、AI视频工…

解析软件测试未来的发展潜力

大家都知道最近 ChatGPT 爆火&#xff0c;国外巨头争相宣布自己的相关计划&#xff0c;国内有点实力的企业也在亦步亦趋地跟进。不出意料的是&#xff0c;关于测试职业要被淘汰的话题又&#xff08;为什么要说又&#xff1f;&#xff09;在扎堆出现&#xff0c;内容跟之前还是大…

软件测试现状以及行业分析

大家都知道最近 ChatGPT 爆火&#xff0c;国外巨头争相宣布自己的相关计划&#xff0c;国内有点实力的企业也在亦步亦趋地跟进。不出意料的是&#xff0c;关于测试职业要被淘汰的话题又&#xff08;为什么要说又&#xff1f;&#xff09;在扎堆出现&#xff0c;内容跟之前还是大…

基于OpenGL的地形建模技术的研究与实现

毕业论文 基于OpenGL的地形建模技术的研究与实现 诚信声明 本人郑重声明&#xff1a;本设计&#xff08;论文&#xff09;及其研究工作是本人在指导教师的指导下独立完成的&#xff0c;在完成设计&#xff08;论文&#xff09;时所利用的一切资料均已在参考文献中列出。 本人签…

国际web短信软件平台开发定制接口通道分类|移讯云短信系统

国际web短信软件平台开发定制接口通道分类|移讯云短信系统 平台外放接口介绍 支持接入CMPP接口&#xff0c;支持SMPP通道接入&#xff0c;支持外放CMPP接口&#xff08;其他平台可以通过CMPP接入我平台&#xff09;&#xff0c;支持HTTP API JSON 接口&#xff0c;支持HTTP A…

短信API接口

一、关于短信API接口 第三方短信服务商提供短信API接口&#xff0c;短信一般是编辑好内容&#xff0c;调用接口发送即可。我们这里提供一个注册好的账号&#xff0c;其中短信API服务器地址为&#xff1a; https://itdage.com/kkb/kkbsms 参数列表为&#xff1a; key&#xff1a…

国际短信系统平台发送接口说明方法|网页短信平台开发搭建-移讯云短信系统

国际短信系统平台发送接口说明方法|网页短信平台开发搭建-移讯云短信系统 此接口为发送接口可直接通过pos直接调用 直接发送&#xff0c;源码短信平台搭建平台时 包含此功能&#xff0c;在客户端中可查看API接口文档 接口名称&#xff1a;自定义短信发送接口 接口方式&#x…

短信平台哪个好用?记录短信接口使用感受

目前市场上的企业短信平台众多&#xff0c;主要分为三大类&#xff0c;即国内三大运营商、云短信平台和专一短信平台服务商。那么哪些短信平台更好用呢&#xff1f; 其实没有最好的短信群发平台&#xff0c;只有最适合的短信群发平台&#xff0c;不同类型的短信平台都有自己的…

各大短信平台接入方法

短信平台有哪些 最为著名的三大平台&#xff1a;华为短信、阿里短信、腾讯短信&#xff1b;根据各家官网的接入文档进行使用 短信平台接入流程 需要具备哪些信息 各家所需信息不太相同&#xff0c;大致如下&#xff1a; 1.app key 2.app 秘钥 3.app 签名 3.发送者id 4.模版&…

发送短信工具类(亿美短信平台接口)

&#xfeff;&#xfeff; 一般我们都是需要接入第三方短信平台&#xff0c;我这边是接入亿美的短信平台sdk&#xff0c;在我们的项目中只需要导入emayclient.jar就可以使用发送接口&#xff0c;当然前提是你有账户和密码&#xff0c;就涉及到购买了。不过其他不多讲&#xff0…

国际web短信软件平台开发搭建后台功能|移讯云短信系统

国际web短信软件平台开发搭建后台功能|移讯云短信系统 特色功能模块功能列表 1&#xff1a;通道路由模块 1.1&#xff1a;通道地区设置 1.2&#xff1a;通道关键词分流 1.3&#xff1a;白名单独立通道设置 1.4&#xff1a;通道分组设置 1.5&#xff1a;通道分组分配 1.6…

调用Android短信软件进行短信群发

最近想做一个可以群发短信的功能&#xff0c;但又不想自己做一个发短信的界面&#xff0c;之前也做过利用Intent调用系统发短信功能&#xff0c;这个网上也有大把人发过。 String mobile "18900000000" Intent intent new Intent(Intent.ACTION_VIE…

短信接口平台

最近忙着弄短信接口的平台程序&#xff0c;现在已经基本做完&#xff0c;跑起来看着还挺顺的。我简单介绍一下。 详细说明 中国电信和中国移动的短信协议要求客户端主动连接到网关收取信息&#xff0c;并且接受的连接只能有一个。因此客户端的接收程序必须尽快处理收到的信息…

什么是短信平台api接口?

自从人类诞生了手机&#xff0c;短信便随之而来&#xff0c;虽然后来有了更多的即时通信工具&#xff0c;如QQ和微信&#xff0c;个人用短信的机会已经很少了&#xff0c;但是对于企业公司来说&#xff0c;短信一直是非常方便的信息传递工具。 那些带有营销性质的企业和商家会通…

营销短信API,免费接口

接口地址: https://api.kertennet.com/live/sms 返回格式: json 请求方式: GET 请求示例: https://api.kertennet.com/live/sms?text短信代发&sign可腾代发&phoneNum1782016XXXX 请求参数说明&#xff1a; 返回数据&#xff1a;