23 changed files with 308 additions and 27 deletions

No files matched your search

+11
View File
@@ -1 +1,12 @@
# ArgoCD Example Apps
This repository contains example ksonnet applications for demoing ArgoCD functionality. Feel free
to register this repository to your ArgoCD instance, or fork this repo and push your own commits
to explore ArgoCD and GitOps!
| Application | Description |
|-------------|-------------|
| [guestbook](guestbook/) | The ksonnet hello word application |
| [pre-post-sync](pre-post-sync/) | Demonstrates ArgoCD PreSync and PostSync hooks |
| [blue-green-deploy](blue-green-deploy/) | Demonstrates an ArgoCD Sync hook which performs a blue/green deployment |
| [sock-shop](sock-shop/) | A microservices demo application (https://microservices-demo.github.io) |
-3
View File
@@ -1,3 +0,0 @@
workflows:
- name: blue-green
path: workflows/bluegreen.yaml
@@ -1,5 +1,5 @@
local env = std.extVar("__ksonnet/environments");
local params = std.extVar("__ksonnet/params").components["bg-deploy"];
local params = std.extVar("__ksonnet/params").components["bg-guestbook"];
[
{
"apiVersion": "v1",
@@ -7,9 +7,7 @@ local params = std.extVar("__ksonnet/params").components["bg-deploy"];
"metadata": {
"name": params.name,
"annotations": {
"argocd.argoproj.io/workflow-sync": "blue-green",
"argocd.argoproj.io/workflow-param.blue-green.service-name": params.name,
"argocd.argoproj.io/workflow-param.blue-green.new-service-manifest": "{{manifest}}",
"argocd.argoproj.io/hook": "Skip",
},
},
"spec": {
@@ -31,9 +29,7 @@ local params = std.extVar("__ksonnet/params").components["bg-deploy"];
"metadata": {
"name": params.name,
"annotations": {
"argocd.argoproj.io/workflow-sync": "blue-green",
"argocd.argoproj.io/workflow-param.blue-green.deployment-name": params.name,
"argocd.argoproj.io/workflow-param.blue-green.new-deployment-manifest": "{{manifest}}",
"argocd.argoproj.io/hook": "Skip",
},
},
"spec": {
@@ -0,0 +1,20 @@
local bgGuestbook = std.extVar("__ksonnet/components")["bg-guestbook"];
local bgGuestbookSvc = bgGuestbook[0];
local bgGuestbookDeploy = bgGuestbook[1];
local parseYaml = std.native("parseYaml");
local bgWorkflow = parseYaml(importstr 'wf/bluegreen.yaml')[0];
[
bgWorkflow + {
spec +: {
arguments +: {
parameters : [
{name: "deployment-name", value: bgGuestbookDeploy.metadata.name},
{name: "service-name", value: bgGuestbookSvc.metadata.name},
{name: "new-deployment-manifest", value: std.manifestJson(bgGuestbookDeploy)},
{name: "new-service-manifest", value: std.manifestJson(bgGuestbookSvc)},
],
},
},
}
]
@@ -6,13 +6,14 @@
components: {
// Component-level parameters, defined initially from 'ks prototype use ...'
// Each object below should correspond to a component in the components/ directory
"bg-deploy": {
"bg-guestbook": {
containerPort: 80,
image: "gcr.io/heptio-images/ks-guestbook-demo:0.1",
name: "bg-deploy",
image: "gcr.io/heptio-images/ks-guestbook-demo:0.2",
name: "bg-guestbook",
replicas: 3,
servicePort: 80,
type: "LoadBalancer",
},
"bg-workflow": {},
},
}
@@ -1,11 +1,13 @@
# This workflow performs a "blue-green" deployment, while preserving the original deployment object
# and name. It accomplishes this by temporarily redirecting traffic to a *clone* of the original
# deployment, then after upgrading the original deployment to a later version, transfering traffic
# deployment. Then after upgrading the original deployment to a later version, redirects traffic
# back to the original (now upgraded) deployment.
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: k8s-bluegreen-
annotations:
argocd.argoproj.io/hook: Sync
spec:
entrypoint: k8s-bluegreen
arguments:
@@ -68,30 +70,53 @@ spec:
# end of steps
# clone deployment creates a "blue" clone of an existing deployment.
# -blue is appended to the metadata.name, as well as the values in the spec.selector.matchLabels,
# and spec.template.metadata.labels
# clone-deployment creates a "blue" clone of an existing deployment. The string -blue is appended to:
# - metadata.name
# - spec.selector.matchLabels
# - spec.template.metadata.labels
- name: clone-deployment
container:
image: argoproj/argoexec:v2.1.1
command: [sh, -c, -x]
args:
- kubectl get --export -o json deployment.apps/{{workflow.parameters.deployment-name}} > /tmp/original-deploy &&
- kubectl get --export -o json deployment.apps/{{workflow.parameters.deployment-name}} > /original-deploy &&
jq -r '.metadata.name+="-blue" |
.spec.template.metadata.labels += (.spec.template.metadata.labels | to_entries | map(select(.key != "applications.argoproj.io/app-name")) | map(.value+="-blue") | from_entries) |
.spec.selector.matchLabels += (.spec.selector.matchLabels | to_entries | map(select(.key != "applications.argoproj.io/app-name")) | map(.value+="-blue") | from_entries)'
/tmp/original-deploy > /tmp/cloned-deploy &&
cat /tmp/cloned-deploy &&
kubectl apply -o yaml -f /tmp/cloned-deploy
/original-deploy > /cloned-deploy &&
cat /cloned-deploy &&
kubectl apply -o yaml -f /cloned-deploy
# apply-manifest takes a kubernetes manifest and carrys over the app-name label (if present)
# before running `kubectl apply`. The label is used by ArgoCD for monitoring.
- name: apply-manifest
inputs:
parameters:
- name: manifest
resource:
action: apply
manifest: '{{inputs.parameters.manifest}}'
artifacts:
- name: manifest-file
path: /manifest
raw:
data: '{{inputs.parameters.manifest}}'
container:
image: argoproj/argoexec:v2.1.1
command: [sh, -c, -x]
args:
- cp /manifest /manifest-new &&
APP_NAME=$(kubectl get -n default -f /manifest-new -o json | jq -r '.metadata.labels."applications.argoproj.io/app-name"') &&
if [ "$APP_NAME" != "null" ]; then
jq -r --arg APP_NAME "$APP_NAME" '.metadata.labels."applications.argoproj.io/app-name" = $APP_NAME' /manifest-new > /manifest-new.tmp &&
mv /manifest-new.tmp /manifest-new &&
if [ "$(jq -r .spec.template.metadata.labels /manifest-new)" != "null" ]; then
jq -r --arg APP_NAME "$APP_NAME" '.spec.template.metadata.labels."applications.argoproj.io/app-name" = $APP_NAME' /manifest-new > /manifest-new.tmp &&
mv /manifest-new.tmp /manifest-new ;
fi ;
fi &&
cat /manifest-new &&
kubectl apply -f /manifest-new
# wait-deployment-ready waits for a deployment to become fully deployed and ready, using the
# `kubectl rollout` command
- name: wait-deployment-ready
inputs:
parameters:
@@ -100,14 +125,15 @@ spec:
image: argoproj/argoexec:v2.1.1
command: [kubectl, rollout, status, --watch=true, 'deployments/{{inputs.parameters.deployment-name}}']
# patch-service updates the service selector labels to point to the "blue" deployment
- name: patch-service
container:
image: argoproj/argoexec:v2.1.1
command: [sh, -c, -x]
args:
- kubectl get -n default service {{workflow.parameters.service-name}} --export -o json > /tmp/original-svc &&
jq '.spec.selector = (.spec.selector | with_entries(.value+="-blue"))' /tmp/original-svc > /tmp/blue-svc &&
kubectl apply -o yaml -f /tmp/blue-svc
- kubectl get -n default service {{workflow.parameters.service-name}} --export -o json > /original-svc &&
jq '.spec.selector = (.spec.selector | with_entries(.value+="-blue"))' /original-svc > /blue-svc &&
kubectl apply -o yaml -f /blue-svc
- name: delete-deployment
resource:
+12
View File
@@ -6,6 +6,18 @@ environments:
server: https://kubernetes.default.svc
k8sVersion: v1.10.0
path: default
dev:
destination:
namespace: dev
server: https://kubernetes.default.svc
k8sVersion: v1.10.0
path: dev
prod:
destination:
namespace: prod
server: https://kubernetes.default.svc
k8sVersion: v1.10.0
path: prod
kind: ksonnet.io/app
name: guestbook
version: 0.0.1
@@ -0,0 +1,2 @@
{
}
+8
View File
@@ -0,0 +1,8 @@
local base = import "base.libsonnet";
// uncomment if you reference ksonnet-lib
// local k = import "k.libsonnet";
base + {
// Insert user-specified overrides here. For example if a component is named \"nginx-deployment\", you might have something like:\n")
// "nginx-deployment"+: k.deployment.mixin.metadata.labels({foo: "bar"})
}
@@ -0,0 +1,17 @@
local params = std.extVar("__ksonnet/params");
local globals = import "globals.libsonnet";
local envParams = params + {
components +: {
// Insert component parameter overrides here. Ex:
// guestbook +: {
// name: "guestbook-dev",
// replicas: params.global.replicas,
// },
},
};
{
components: {
[x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components)
},
}
@@ -0,0 +1,2 @@
{
}
+8
View File
@@ -0,0 +1,8 @@
local base = import "base.libsonnet";
// uncomment if you reference ksonnet-lib
// local k = import "k.libsonnet";
base + {
// Insert user-specified overrides here. For example if a component is named \"nginx-deployment\", you might have something like:\n")
// "nginx-deployment"+: k.deployment.mixin.metadata.labels({foo: "bar"})
}
@@ -0,0 +1,17 @@
local params = std.extVar("__ksonnet/params");
local globals = import "globals.libsonnet";
local envParams = params + {
components +: {
// Insert component parameter overrides here. Ex:
// guestbook +: {
// name: "guestbook-dev",
// replicas: params.global.replicas,
// },
},
};
{
components: {
[x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components)
},
}
+4
View File
@@ -0,0 +1,4 @@
/lib
/.ksonnet/registries
/app.override.yaml
/.ks_environment
+11
View File
@@ -0,0 +1,11 @@
apiVersion: 0.1.0
environments:
default:
destination:
namespace: default
server: https://kubernetes.default.svc
k8sVersion: v1.10.0
path: default
kind: ksonnet.io/app
name: pre-post-sync
version: 0.0.1
@@ -0,0 +1,66 @@
local env = std.extVar("__ksonnet/environments");
local params = std.extVar("__ksonnet/params").components["guestbook-ui"];
[
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": params.name
},
"spec": {
"ports": [
{
"port": params.servicePort,
"targetPort": params.containerPort
}
],
"selector": {
"app": params.name
},
"type": params.type
}
},
{
"apiVersion": "apps/v1beta2",
"kind": "Deployment",
"metadata": {
"name": params.name
},
"spec": {
"replicas": params.replicas,
"selector": {
"matchLabels": {
"app": params.name
},
},
"template": {
"metadata": {
"labels": {
"app": params.name
}
},
"spec": {
"containers": [
{
"image": params.image,
"name": params.name,
"ports": [
{
"containerPort": params.containerPort
}
],
// dummy readiness probe to slow down the rollout for demo/testing
"readinessProbe": {
"exec": {
"command": [ "sh", "-c", "exit 0" ],
},
"initialDelaySeconds": 10,
"periodSeconds": 30,
}
}
]
}
}
}
}
]
+20
View File
@@ -0,0 +1,20 @@
{
global: {
// User-defined global parameters; accessible to all component and environments, Ex:
// replicas: 4,
},
components: {
// Component-level parameters, defined initially from 'ks prototype use ...'
// Each object below should correspond to a component in the components/ directory
"guestbook-ui": {
containerPort: 80,
image: "gcr.io/heptio-images/ks-guestbook-demo:0.2",
name: "pre-post-sync",
replicas: 1,
servicePort: 80,
type: "ClusterIP",
},
"pre-sync-job": {},
"post-sync-job": {},
},
}
@@ -0,0 +1,16 @@
apiVersion: batch/v1
kind: Job
metadata:
generateName: after-
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: OnSuccess
spec:
template:
spec:
containers:
- name: sleep
image: alpine:latest
command: ["sleep", "10"]
restartPolicy: Never
backoffLimit: 0
@@ -0,0 +1,16 @@
apiVersion: batch/v1
kind: Job
metadata:
generateName: before-
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: OnSuccess
spec:
template:
spec:
containers:
- name: sleep
image: alpine:latest
command: ["sleep", "10"]
restartPolicy: Never
backoffLimit: 0
@@ -0,0 +1,4 @@
local components = std.extVar("__ksonnet/components");
components + {
// Insert user-specified overrides here.
}
@@ -0,0 +1,2 @@
{
}
@@ -0,0 +1,8 @@
local base = import "base.libsonnet";
// uncomment if you reference ksonnet-lib
// local k = import "k.libsonnet";
base + {
// Insert user-specified overrides here. For example if a component is named \"nginx-deployment\", you might have something like:\n")
// "nginx-deployment"+: k.deployment.mixin.metadata.labels({foo: "bar"})
}
@@ -0,0 +1,17 @@
local params = std.extVar("__ksonnet/params");
local globals = import "globals.libsonnet";
local envParams = params + {
components +: {
// Insert component parameter overrides here. Ex:
// guestbook +: {
// name: "guestbook-dev",
// replicas: params.global.replicas,
// },
},
};
{
components: {
[x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components)
},
}