Argo Rollouts结合Service进行Blue-Green部署
删除03 部署04
root@k8s-master01:~/learning-jenkins-cicd/09-argocd-and-rollout/rollout-demos# kubectl delete -f 03-rollouts-with-prometheus-analysis.yaml
root@k8s-master01:~/learning-jenkins-cicd/09-argocd-and-rollout/rollout-demos# kubectl apply -f 04-rollouts-bluegreen-demo.yaml
更新镜像
root@k8s-master01:~/k8s-prom# kubectl rollouts set image rollout-helloworld-bluegreen spring-boot-helloworld=ikubernetes/demoapp:v1.0
rollout "rollout-helloworld-bluegreen" image updated
会
虽然新版已经启动,但外部流量依旧访问得是旧版本,此时在图形界面手动切换promote,切换后会发现流量切换到新版本上
删除04,开启05
kubectl apply -f 05-rollouts-bluegreen-with-analysis.yaml
开启错误请求
while true ; do curl hello.magedu.com/dd ;sleep 2;done
执行更新
root@k8s-master01:~/k8s-prom# kubectl get rollouts.argoproj.io
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
rollout-helloworld-bluegreen-with-analysis 3 3 3 3 48s
root@k8s-master01:~/k8s-prom# kubectl rollout
rollout (Manage the rollout of a resource) rollouts (The command rollouts is a plugin installed by the user)
root@k8s-master01:~/k8s-prom# kubectl rollouts set image rollout-helloworld-bluegreen-with-analysis spring-boot-helloworld=ikubernetes/demoapp:v1.0
rollout "rollout-helloworld-bluegreen-with-analysis" image update
删除05
root@k8s-master01:~/learning-jenkins-cicd/09-argocd-and-rollout/rollout-demos# kubectl delete -f 05-rollouts-bluegreen-with-analysis.yaml
将gitlab中spring-boot-helloWorld/rollouts/rollouts-canary-demo.yaml替换为/learning-jenkins-cicd/09-argocd-and-rollout/rollout-demos/03-rollouts-with-prometheus-analysis.yaml
重建jenkins
root@k8s-master01:~/learning-k8s/jenkins# kubectl apply -f deploy/
root@k8s-master01:~/learning-k8s/jenkins# kubectl apply -f deploy/
查看token
jenkins@jenkins-dc5478948-tw7gc:/$ cat /var/run/secrets/kubernetes.io/serviceaccount/token && echo
eyJhbGciOiJSUzI1NiIsImtpZCI6IklQaC1rY29PSDVqMlZGblpYbVpwMGhzN0V2Nm5jSFNTd3Vmc1dBQ0dTa1EifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzMxOTExMzcwLCJpYXQiOjE3MDAzNzUzNzAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJqZW5raW5zIiwicG9kIjp7Im5hbWUiOiJqZW5raW5zLWRjNTQ3ODk0OC10dzdnYyIsInVpZCI6IjdkN2U1ZDU4LTYyZjgtNGZmMS04ODUzLWIzZjhmMWVhNTExYyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiamVua2lucy1tYXN0ZXIiLCJ1aWQiOiI5ZjEwOTgyNi0yOTE0LTRlNDgtODUwYS1iNjUwMmQ0M2M1ZWEifSwid2FybmFmdGVyIjoxNzAwMzc4OTc3fSwibmJmIjoxNzAwMzc1MzcwLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6amVua2luczpqZW5raW5zLW1hc3RlciJ9.iSRsLe8QGP1WJ18jMf5_CESItiZECh3Y6mo_Ab1EhB8iVFgiFihXzTkOVphqwhvZ5P5ofZ-gTkfPXVGmkq0AStLBp05gGwtIMmu-OHp-Y-LkYlrE_CUsmu9Oh8mcN33tSWr3n1rP6MNS4LqN0O7LYdW8oJFUZDmuLBfBTLIdN5aeFAmbdfQymjcpGKPM7N1FVU7e9BJk4N8saEvvTfi0Vgkgd8beSF68QJ6IEh4s-aoynUuARxyPRLejoygJNOUcqlsMvJ_cr7cG81mwY4BIxLQTZ6t4wmYgSt_k8yJCIZ271sJqHZyyWWfxSauQYieGx3a4WYRbITQfQHBLPt73AQ
jenkins凭据管理更新凭据
jenkins流水线配置
pipeline {
agent {
kubernetes {
inheritFrom 'maven-docker-kubectl'
}
}
triggers {
GenericTrigger(
genericVariables: [
[key: 'ref', value: '$.ref']
],
token: 'fClZ0e/kTcqL2ARh7YqxW/3ndOCZA2SqfKnRTLat',
causeString: 'Triggered on $ref',
printContributedVariables: true,
printPostContent: true
)
}
environment {
codeRepo="http://192.168.1.50/root/spring-boot-helloWorld.git"
registry='harbor.luohw.net'
registryUrl='https://harbor.luohw.net'
registryCredential='harbor-user-credential'
projectName='spring-boot-helloworld'
imageUrl="${registry}/ikubernetes/${projectName}"
imageTag="${BUILD_ID}"
}
stages {
stage('Source') {
steps {
git branch: 'main', credentialsId: 'gitlab-root-credential', url: "${codeRepo}"
}
}
stage('Build') {
steps {
container('maven') {
sh 'mvn -B -DskipTests clean package'
}
}
}
stage('Test') {
steps {
container('maven') {
sh 'mvn test'
}
}
}
stage("SonarQube Analysis") {
steps {
container('maven') {
withSonarQubeEnv('SonaQube-Server') {
sh 'mvn sonar:sonar'
}
}
}
}
stage("Quality Gate") {
steps {
timeout(time: 30, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
stage('Build Image') {
steps {
container('dind') {
script {
dockerImage = docker.build("${imageUrl}:${imageTag}")
}
}
}
}
stage('Push Image') {
steps {
container('dind') {
script {
docker.withRegistry(registryUrl, registryCredential) {
dockerImage.push()
dockerImage.push('latest')
}
}
}
}
}
stage('Update-manifests') {
steps {
container('jnlp') {
sh 'sed -i "s#__IMAGE__#${imageUrl}:${imageTag}#gi" rollouts/rollouts-canary-demo.yaml'
}
}
}
stage('Deploy') {
steps {
container('kubectl') {
withKubeConfig([credentialsId: 'k8s-cicd-admin-credentials', serverUrl: 'https://kubernetes.default.svc']) {
sh '''
kubectl apply -f rollouts/rollouts-canary-demo.yaml -n default
'''
}
}
}
}
}
post{
always{
qyWechatNotification failNotify: true, webhookUrl: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=5530d220-0983-490e-ada5-a74fa66570c8'
}
}
}
deploy失败是因为token会更新,运行测试容器,重新获取token并在jenkins中更新即可
测试容器yaml
root@k8s-master01:~# cat mypod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: mypod
name: mypod
namespace: kube-system
spec:
containers:
- image: ikubernetes/demoapp:v1.0
name: mypod
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
serviceAccountName: k8s-cicd-admin
root@k8s-master01:~# kubectl apply -f mypod.yaml
pod/mypod created
root@k8s-master01:~# kubectl exec -it -n kube-system mypod -- sh
[root@mypod /]# cat /run/secrets/kubernetes.io/serviceaccount/token && echo
eyJhbGciOiJSUzI1NiIsImtpZCI6IklQaC1rY29PSDVqMlZGblpYbVpwMGhzN0V2Nm5jSFNTd3Vmc1dBQ0dTa1EifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzMxOTEyODUzLCJpYXQiOjE3MDAzNzY4NTMsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsInBvZCI6eyJuYW1lIjoibXlwb2QiLCJ1aWQiOiI1ZGEwZWRhYS1lMWQ4LTRhYjItYWUyNy1lY2Q1YWQzYjI4NmEifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6Ims4cy1jaWNkLWFkbWluIiwidWlkIjoiNGQzN2U4MjktOTE5ZS00MDcwLTk4YTUtMDA1YzAwZDAwMzc5In0sIndhcm5hZnRlciI6MTcwMDM4MDQ2MH0sIm5iZiI6MTcwMDM3Njg1Mywic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOms4cy1jaWNkLWFkbWluIn0.pOae_dgto7sXu-yQ4iTegXR-lPYnLKPJXyWt4TcI3fmlgMZqmA4O6SUS_ntAbfnWN6XDNd0x1CvMTVPuXh7DSuJ5RqItXDXAy_xgMf3xMYKV0J9YHo7MJAwpLbupcS2B1sl8_Hpfc-N6lrih_JeAoSzc1sCfUQAjh35VbFB6wkkkAUQfWFSpg2iCT23FZcxyKQIq7P4ixH1LZb8mjFTXuB7229H4GqrQiyVSOq9RsqWDLtB-mH8XUiW3tSWQwpzV15OQ_elFgYVqujA_z3TdMs3BoANM0RKU-E30af5YeR40vTFG6pI2EcE12_Apq39Wvp5RUvx2EcEeWW3xjAJp3w