Argo Rollouts
Argo Rollouts is a Kubernetes controller that provides advanced deployment capabilities such as blue-green, canary, canary analysis, experimentation, and progressive delivery features to Kubernetes. Because Argo Rollouts supports the Kubernetes Gateway API, you can use Argo Rollouts to control how traffic is split and forwarded from the proxies that K8sGateway v2 manages to the apps in your cluster.
Before you begin
-
Follow the Get started guide to install K8sGateway, set up a gateway resource, and deploy the httpbin sample app.
-
Get the external address of the gateway and save it in an environment variable.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n gloo-system gloo-proxy-http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESS
kubectl port-forward deployment/gloo-proxy-http -n gloo-system 8080:8080
Install Argo Rollouts
-
Create the
argo-rollouts
namespace and deploy the Argo Rollouts components into it.kubectl create namespace argo-rollouts kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
-
Change the config map for the Argo Rollouts pod to install the Argo Rollout Gateway API plug-in.
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ConfigMap metadata: name: argo-rollouts-config namespace: argo-rollouts data: trafficRouterPlugins: |- - name: "argoproj-labs/gatewayAPI" location: "https://github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/releases/download/v0.0.0-rc1/gateway-api-plugin-linux-amd64" EOF
-
Restart the Argo Rollouts pod to pick up the latest configuration changes.
kubectl rollout restart deployment -n argo-rollouts argo-rollouts
Create RBAC rules for Argo
-
Create a cluster role to allow the Argo Rollouts pod to manage HTTPRoute resources.
⚠️The following cluster role allows the Argo Rollouts pod to access and work with any resources in the cluster. Use this configuration with caution and only in test environments.kubectl apply -f- <<EOF apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: gateway-controller-role namespace: argo-rollouts rules: - apiGroups: - "*" resources: - "*" verbs: - "*" EOF
-
Create a cluster role binding to give the Argo Rollouts service account the permissions from the cluster role.
kubectl apply -f- <<EOF apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-admin roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: gateway-controller-role subjects: - namespace: argo-rollouts kind: ServiceAccount name: argo-rollouts EOF
Set up a rollout
-
Create a stable and canary service for the
rollouts-demo
pod that you deploy in the next step.kubectl apply -f- <<EOF apiVersion: v1 kind: Service metadata: name: argo-rollouts-stable-service namespace: default spec: ports: - port: 80 targetPort: http protocol: TCP name: http selector: app: rollouts-demo --- apiVersion: v1 kind: Service metadata: name: argo-rollouts-canary-service namespace: default spec: ports: - port: 80 targetPort: http protocol: TCP name: http selector: app: rollouts-demo EOF
-
Create an Argo Rollout that deploys the
rollouts-demo
pod. Add your stable and canary services to thespec.strategy.canary
section.kubectl apply -f- <<EOF apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: rollouts-demo namespace: default spec: replicas: 3 strategy: canary: canaryService: argo-rollouts-canary-service # our created canary service stableService: argo-rollouts-stable-service # our created stable service trafficRouting: plugins: argoproj-labs/gatewayAPI: httpRoute: argo-rollouts-http-route namespace: default steps: - setWeight: 30 - pause: { duration: 30s } - setWeight: 60 - pause: { duration: 30s } - setWeight: 100 - pause: { duration: 30s } revisionHistoryLimit: 2 selector: matchLabels: app: rollouts-demo template: metadata: labels: app: rollouts-demo spec: containers: - name: rollouts-demo image: kostiscodefresh/summer-of-k8s-app:v1 ports: - name: http containerPort: 8080 protocol: TCP resources: requests: memory: 32Mi cpu: 5m EOF
-
Create an HTTPRoute resource to expose the
rollouts-demo
pod on the HTTP gateway that you created as part of the Get started guide. The HTTP resource can serve both the stable and canary versions of your app.kubectl apply -f- <<EOF kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: argo-rollouts-http-route namespace: default spec: parentRefs: - name: http namespace: gloo-system hostnames: - "demo.example.com" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: argo-rollouts-stable-service kind: Service port: 80 - name: argo-rollouts-canary-service kind: Service port: 80 EOF
-
Send a request to the
rollouts-demo
app and verify your CLI output.-
Get the external address of the gateway and save it in an environment variable.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n gloo-system gloo-proxy-http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESS
-
Send a request to the
rollouts-demo
app and verify that you see thever: 1.0
response from the stable service.curl http://$INGRESS_GW_ADDRESS:8080/callme -H "host: demo.example.com:8080"
Example output:
<div class='pod' style='background:#44B3C2'> ver: 1.0 </div>%
-
Port-forward the
gloo-proxy-http
pod on port 8080.kubectl port-forward deployment/gloo-proxy-http -n gloo-system 8080:8080
-
Send a request to the
rollouts-demo
app and verify that you see thever: 1.0
response from the stable service.curl -vik localhost:8080/callme -H "host: demo.example.com"
Example output:
<div class='pod' style='background:#44B3C2'> ver: 1.0 </div>%
-
-
Change the manifest to use the
v2
tag to start a rollout of your app. Argo Rollouts automatically starts splitting traffic between version 1 and version 2 of the app for the duration of the rollout.kubectl patch rollout rollouts-demo -n default \ --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"kostiscodefresh/summer-of-k8s-app:v2"}]'
-
Send another request to your app. Because traffic is split between version 1 and version 2 of the app, you see responses from both app versions until the rollout is completed.
while true; do curl -H "host: demo.example.com" $INGRESS_GW_ADDRESS:8080/callme; done
Example output:
<div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0
while true; do curl localhost:8080/callme -H "host: demo.example.com"; done
Example output:
<div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#44B3C2'> ver: 1.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0 </div><div class='pod' style='background:#F1A94E'> ver: 2.0
Congratulations, you successfully rolled out a new version of your app without downtime by using the HTTP gateway that is managed by K8sGateway v2. After a rollout, you typically perform tasks such as the following:
- Testing: Conduct thorough testing of your app to ensure that it functions correctly after the rollout.
- Monitoring: Monitor your application to detect any issues that may arise after the rollout.
- Documentation: Update documentation or runbooks to reflect any changes in your application.
- User Validation: Have users validate that the app functions correctly and meets their requirements.
- Performance Testing: Depending on your app, consider conducting performance testing to ensure that your app can handle the expected load without issues.
- Resource Cleanup: If the rollout included changes to infrastructure or other resources, ensure that any temporary or unused resources are cleaned up to avoid incurring unnecessary costs.
- Communication: Communicate with your team and stakeholders to update them on the status of the rollout and any issues that were encountered and resolved.
- Security Audit: If your application has undergone significant changes, consider conducting a security audit to ensure that no security vulnerabilities have been introduced.
Cleanup
You can remove the resources that you created in this guide.-
Remove the HTTP route.
kubectl delete httproute argo-rollouts-http-route
-
Remove the Argo Rollout.
kubectl delete rollout rollouts-demo
-
Remove the stable and canary services.
kubectl delete services argo-rollouts-canary-service argo-rollouts-stable-service
-
Remove the cluster role for the Argo Rollouts pod.
kubectl delete clusterrole gateway-controller-role -n argo-rollouts
-
Remove the cluster role binding.
kubectl delete clusterrolebinding gateway-admin
-
Remove Argo Rollouts.
kubectl delete -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml kubectl delete namespace argo-rollouts