forked from docs/doc-exports
Reviewed-by: Eotvos, Oliver <oliver.eotvos@t-systems.com> Co-authored-by: qiujiandong1 <qiujiandong1@huawei.com> Co-committed-by: qiujiandong1 <qiujiandong1@huawei.com>
178 lines
14 KiB
HTML
178 lines
14 KiB
HTML
<a name="cce_bestpractice_10002"></a><a name="cce_bestpractice_10002"></a>
|
|
|
|
<h1 class="topictitle1">Using Services to Implement Simple Grayscale Release and Blue-Green Deployment</h1>
|
|
<div id="body0000001214715927"><p id="cce_bestpractice_10002__p134945762919">To implement grayscale release for a CCE cluster, deploy other open source tools, such as Nginx Ingress, to the cluster or deploy services to a service mesh. These solutions are difficult to implement. If your grayscale release requirements are simple and you do not want to introduce too many plug-ins or complex configurations, you can refer to this section to implement simple grayscale release and blue-green deployment based on native Kubernetes features.</p>
|
|
<div class="section" id="cce_bestpractice_10002__section83181748204815"><h4 class="sectiontitle">Principles</h4><p id="cce_bestpractice_10002__p9721204914488">Users usually use Kubernetes objects such as Deployments and StatefulSets to deploy services. Each workload manages a group of pods. The following figure uses Deployment as an example.</p>
|
|
<p id="cce_bestpractice_10002__p83034205119"><span><img id="cce_bestpractice_10002__image1430312011113" src="en-us_image_0000002218818630.png"></span></p>
|
|
<p id="cce_bestpractice_10002__p99543095117">Generally, a Service is created for each workload. The Service uses the selector to match the backend pod. Other Services or objects outside the cluster can access the pods backing the Service. If a pod needs to be exposed, set the Service type to LoadBalancer. The ELB load balancer functions as the traffic entrance.</p>
|
|
<ul id="cce_bestpractice_10002__ul496444661313"><li id="cce_bestpractice_10002__li10964164631319"><strong id="cce_bestpractice_10002__b798201619015">Grayscale release principles</strong><p id="cce_bestpractice_10002__p1937157151310">Take a Deployment as an example. A Service, in most cases, will be created for each Deployment. However, Kubernetes does not require that Services and Deployments correspond to each other. A Service uses a selector to match backend pods. If pods of different Deployments are selected by the same selector, a Service corresponds to multiple versions of Deployments. You can adjust the number of replicas of Deployments of different versions to adjust the weights of services of different versions to achieve grayscale release. The following figure shows the process:</p>
|
|
<p id="cce_bestpractice_10002__p16985419414"><span><img id="cce_bestpractice_10002__image136935424112" src="en-us_image_0000002253778453.png"></span></p>
|
|
</li><li id="cce_bestpractice_10002__li7237164816139"><strong id="cce_bestpractice_10002__b138751414299">Blue-green deployment principles</strong><p id="cce_bestpractice_10002__p890755681315">Take a Deployment as an example. Two Deployments of different versions have been deployed in the cluster, and their pods are labeled with the same key but different values to distinguish versions. A Service uses the selector to select the pod of a Deployment of a version. In this case, you can change the value of the label that determines the version in the Service selector to change the pod backing the Service. In this way, you can directly switch the service traffic from one version to another. The following figure shows the process:</p>
|
|
<p id="cce_bestpractice_10002__p15687143993520"><span><img id="cce_bestpractice_10002__image368773913510" src="en-us_image_0000002253618529.png"></span></p>
|
|
</li></ul>
|
|
</div>
|
|
<div class="section" id="cce_bestpractice_10002__section17736476474"><h4 class="sectiontitle">Prerequisites</h4><p id="cce_bestpractice_10002__p10789251104217">The Nginx image has been uploaded to SWR. The Nginx images have two versions: v1 and v2. The welcome pages are <strong id="cce_bestpractice_10002__b246092220173">Nginx-v1</strong> and <strong id="cce_bestpractice_10002__b64421260176">Nginx-v2</strong>.</p>
|
|
</div>
|
|
<div class="section" id="cce_bestpractice_10002__section5306945183515"><h4 class="sectiontitle">Resource Creation</h4><p id="cce_bestpractice_10002__p929922183219">You can use YAML to deploy Deployments and Services in either of the following ways:</p>
|
|
<ul id="cce_bestpractice_10002__ul130263943212"><li id="cce_bestpractice_10002__li15359104173218">On the <strong id="cce_bestpractice_10002__b13266145019173">Create Deployment</strong> page, click <strong id="cce_bestpractice_10002__b689918543179">Create YAML</strong> on the right and edit the YAML file in the window.</li><li id="cce_bestpractice_10002__li730203933212">Save the sample YAML file in this section as a file and use kubectl to specify the YAML file. For example, run the <strong id="cce_bestpractice_10002__b484014972314">kubectl create -f xxx.yaml</strong> command.</li></ul>
|
|
</div>
|
|
<div class="section" id="cce_bestpractice_10002__section1111011567298"><h4 class="sectiontitle">Step 1: Deploy Services of Two Versions</h4><p id="cce_bestpractice_10002__p15357640174610">Two versions of Nginx services are deployed in the cluster to provide external access through ELB.</p>
|
|
<ol id="cce_bestpractice_10002__ol026510278444"><li id="cce_bestpractice_10002__li182659278445"><span>Create a Deployment of the first version. The following uses nginx-v1 as an example. Example YAML:</span><p><pre class="screen" id="cce_bestpractice_10002__screen1238910449211">apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: nginx-v1
|
|
spec:
|
|
replicas: 2 # Number of replicas of the Deployment, that is, the number of pods
|
|
selector: # Label selector
|
|
matchLabels:
|
|
app: nginx
|
|
version: v1
|
|
template:
|
|
metadata:
|
|
labels: # Pod label
|
|
app: nginx
|
|
version: v1
|
|
spec:
|
|
containers:
|
|
- image: {your_repository}/nginx:v1 # The image used by the container is nginx:v1.
|
|
name: container-0
|
|
resources:
|
|
limits:
|
|
cpu: 100m
|
|
memory: 200Mi
|
|
requests:
|
|
cpu: 100m
|
|
memory: 200Mi
|
|
imagePullSecrets:
|
|
- name: default-secret</pre>
|
|
</p></li><li id="cce_bestpractice_10002__li16787948005"><span>Create a Deployment of the second version. The following uses nginx-v2 as an example. Example YAML:</span><p><pre class="screen" id="cce_bestpractice_10002__screen1778794817016">apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: nginx-v2
|
|
spec:
|
|
replicas: 2 # Number of replicas of the Deployment, that is, the number of pods
|
|
selector: # Label selector
|
|
matchLabels:
|
|
app: nginx
|
|
version: v2
|
|
template:
|
|
metadata:
|
|
labels: # Pod label
|
|
app: nginx
|
|
version: v2
|
|
spec:
|
|
containers:
|
|
- image: {your_repository}/nginx:v2 # The image used by the container is nginx:v2.
|
|
name: container-0
|
|
resources:
|
|
limits:
|
|
cpu: 100m
|
|
memory: 200Mi
|
|
requests:
|
|
cpu: 100m
|
|
memory: 200Mi
|
|
imagePullSecrets:
|
|
- name: default-secret</pre>
|
|
<p id="cce_bestpractice_10002__p578719484016">You can log in to the CCE console to view the deployment status.</p>
|
|
</p></li></ol>
|
|
</div>
|
|
<div class="section" id="cce_bestpractice_10002__section911135614291"><h4 class="sectiontitle">Step 2: Implement Grayscale Release</h4><ol id="cce_bestpractice_10002__ol21285238187"><li id="cce_bestpractice_10002__li0128122361820"><span>Create a LoadBalancer Service for the Deployment. Do not specify the version in the selector. Enable the Service to select the pods of the Deployments of two versions. Example YAML:</span><p><pre class="screen" id="cce_bestpractice_10002__screen131282232184">apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
annotations:
|
|
kubernetes.io/elb.id: 586c97da-a47c-467c-a615-bd25a20de39c # ID of the ELB load balancer. Replace it with the actual value.
|
|
name: nginx
|
|
spec:
|
|
ports:
|
|
- name: service0
|
|
port: 80
|
|
protocol: TCP
|
|
targetPort: 80
|
|
selector: # The selector does not contain version information.
|
|
app: nginx
|
|
type: LoadBalancer # Service type (LoadBalancer)</pre>
|
|
</p></li><li id="cce_bestpractice_10002__li13128423151810"><span>Run the following command to test the access:</span><p><p id="cce_bestpractice_10002__p1912852331818"><strong id="cce_bestpractice_10002__b171281323131811">for i in {1..10}; do curl </strong><EXTERNAL_IP><strong id="cce_bestpractice_10002__b0128122319184">; done;</strong></p>
|
|
<p id="cce_bestpractice_10002__p13128172331813"><EXTERNAL_IP> indicates the IP address of the ELB load balancer.</p>
|
|
<p id="cce_bestpractice_10002__p19128123101819">The command output is as follows (Half of the responses are from the Deployment of version v1, and the other half are from version v2):</p>
|
|
<pre class="screen" id="cce_bestpractice_10002__screen1512892391811">Nginx-v2
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v2
|
|
Nginx-v1
|
|
Nginx-v2
|
|
Nginx-v1
|
|
Nginx-v2
|
|
Nginx-v2</pre>
|
|
</p></li><li id="cce_bestpractice_10002__li01281123141812"><span>Use the console or kubectl to adjust the number of replicas of the Deployments. Change the number of replicas to 4 for v1 and 1 for v2.</span><p><p id="cce_bestpractice_10002__p19907820174510"><strong id="cce_bestpractice_10002__b6516182514518">kubectl scale deployment/nginx-v1 --replicas=4</strong></p>
|
|
<p id="cce_bestpractice_10002__p8907102015457"><strong id="cce_bestpractice_10002__b451718252455">kubectl scale deployment/nginx-v2 --replicas=1</strong></p>
|
|
</p></li><li id="cce_bestpractice_10002__li312962311816"><span>Run the following command to test the access again:</span><p><p id="cce_bestpractice_10002__p21292023171818"><strong id="cce_bestpractice_10002__b012916232180">for i in {1..10}; do curl </strong><EXTERNAL_IP><strong id="cce_bestpractice_10002__b18129623201813">; done;</strong></p>
|
|
<p id="cce_bestpractice_10002__p11293231188"><EXTERNAL_IP> indicates the IP address of the ELB load balancer.</p>
|
|
<p id="cce_bestpractice_10002__p121291823201813">In the command output, among the 10 access requests, only two responses are from the v2 version. The response ratio of the v1 and v2 versions is the same as the ratio of the number of replicas of the v1 and v2 versions, that is, 4:1. Grayscale release is implemented by controlling the number of replicas of services of different versions.</p>
|
|
<pre class="screen" id="cce_bestpractice_10002__screen812914236187">Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v2
|
|
Nginx-v1
|
|
Nginx-v2
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1</pre>
|
|
<div class="note" id="cce_bestpractice_10002__note263143615510"><img src="public_sys-resources/note_3.0-en-us.png"><span class="notetitle"> </span><div class="notebody"><p id="cce_bestpractice_10002__p1563936105116">If the ratio of v1 to v2 is not 4:1, you can set the number of access times to a larger value, for example, 20. Theoretically, the more the times, the closer the response ratio between v1 and v2 is to 4:1.</p>
|
|
</div></div>
|
|
</p></li></ol>
|
|
</div>
|
|
<div class="section" id="cce_bestpractice_10002__section61141756112911"><h4 class="sectiontitle">Step 3: Implement Blue-Green Deployment</h4><ol id="cce_bestpractice_10002__ol143411558191711"><li id="cce_bestpractice_10002__li53411358111717"><span>Create a LoadBalancer Service for a deployed Deployment and specify that the v1 version is used. Example YAML:</span><p><pre class="screen" id="cce_bestpractice_10002__screen1980404861810">apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
annotations:
|
|
kubernetes.io/elb.id: 586c97da-a47c-467c-a615-bd25a20de39c # ID of the ELB load balancer. Replace it with the actual value.
|
|
name: nginx
|
|
spec:
|
|
ports:
|
|
- name: service0
|
|
port: 80
|
|
protocol: TCP
|
|
targetPort: 80
|
|
selector: # Set the version to v1 in the selector.
|
|
app: nginx
|
|
version: v1
|
|
type: LoadBalancer # Service type (LoadBalancer)</pre>
|
|
</p></li><li id="cce_bestpractice_10002__li14997203617186"><span>Run the following command to test the access:</span><p><p id="cce_bestpractice_10002__p1359215919219"><strong id="cce_bestpractice_10002__b108271505312">for i in {1..10}; do curl </strong><EXTERNAL_IP><strong id="cce_bestpractice_10002__b2013195413314">; done;</strong></p>
|
|
<p id="cce_bestpractice_10002__p199536461433"><EXTERNAL_IP> indicates the IP address of the ELB load balancer.</p>
|
|
<p id="cce_bestpractice_10002__p6605171942">The command output is as follows (all responses are from the v1 version):</p>
|
|
<pre class="screen" id="cce_bestpractice_10002__screen265211111250">Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1
|
|
Nginx-v1</pre>
|
|
</p></li><li id="cce_bestpractice_10002__li95104365181"><span>Use the console or kubectl to modify the selector of the Service so that the v2 version is selected.</span><p><p id="cce_bestpractice_10002__p1653718979"><strong id="cce_bestpractice_10002__b81393522131">kubectl patch service nginx -p '{"spec":{"selector":{"version":"v2"}}}'</strong></p>
|
|
</p></li><li id="cce_bestpractice_10002__li69641356188"><span>Run the following command to test the access again:</span><p><p id="cce_bestpractice_10002__p5873112710157"><strong id="cce_bestpractice_10002__b19873172716157">for i in {1..10}; do curl </strong><EXTERNAL_IP><strong id="cce_bestpractice_10002__b19873172731512">; done;</strong></p>
|
|
<p id="cce_bestpractice_10002__p2087332710153"><EXTERNAL_IP> indicates the IP address of the ELB load balancer.</p>
|
|
<p id="cce_bestpractice_10002__p2873027131516">The returned results show that are all responses are from the v2 version. The blue-green deployment is successfully implemented.</p>
|
|
<pre class="screen" id="cce_bestpractice_10002__screen18211124012164">Nginx-v2
|
|
Nginx-v2
|
|
Nginx-v2
|
|
Nginx-v2
|
|
Nginx-v2
|
|
Nginx-v2
|
|
Nginx-v2
|
|
Nginx-v2
|
|
Nginx-v2
|
|
Nginx-v2</pre>
|
|
</p></li></ol>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="familylinks">
|
|
<div class="parentlink"><strong>Parent topic:</strong> <a href="cce_bestpractice_10000.html">Release</a></div>
|
|
</div>
|
|
</div>
|
|
|