Skip to main content

Slack

Slack is a messaging service that many companies have adopted for internal communication. Is this necessary for the project that I have built? No but there is a nice feature in ArgoCD that can push notifications to your slack channels. This can be helpful as it gives you notifications on when things change in your Kubernetes clusters. In addition, I also use this to subscribe to GitHub repositories to be notified when there are pull requests or version changes in my ArgoCD Manifests.

Git Integration

Once you have a Slack organization setup (It's quite easy to make one, just follow the signup steps), you will need to go to Manage Apps.

Slack Manage Apps

Search for GitHub and install it

GitHub Integration

In general, what I recommend is for the microservice type you have, you should subscribe that repository to that channel. To do so, run:

github /subscribe [owner/repo]

For example, if I have a repository named clock, I would run github /subscribe 0toalpha/clock in the channel #clock. This will give me all the updates when there have been commits push or when pull requests have been made.

Kubernetes Integration

A nice feature with Kubernetes is once we have it installed, we can have notifications pushed to Slack and this can be information on when new versions have been pushed and the cluster is updating it. To do so, we should create two channels, one called #staging and the other called #production. In an internet browser, navigate to Manage Your Apps and select 'Create New App'.

Create New App

Select 'From Scratch'

From Scratch

Name App and Select Workspace

App Settings

Now go to OAuth & Permissions

Permissions

tip

Save the Bot User OAuth Token, you will need this later for ArgoCD Notifications.

App Token

Go to Scopes and add chat:write

Scope

In your Slack Client, the one you installed, go to the channel and select integrations.

Channel Details

Go to Integrations and select Add Apps

Add Apps

Search for your App

Add ArgoCD

Now back onto our kubernetes server machines, we will need to install ArgoCD-Notifications. On each Kubernetes server run the following:

kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/notifications_catalog/install.yaml

You will now need to apply the notification configuration, to do so make a file called slackNotifications.yaml and add the following:

warning

Replace the following:

  • SLACK_TOKEN
  • EMAIL_HOST
  • EMAIL_PORT
  • EMAIL_USERNAME
  • EMAIL_PASSWORD
  • EMAIL_ADDRESS
apiVersion: v1
kind: Secret
metadata:
name: argocd-notifications-secret
namespace: argocd
stringData:
slack-token: SLACK_TOKEN
email-host: EMAIL_HOST
email-port: EMAIL_PORT
email-username: EMAIL_USERNAME
email-password: EMAIL_PASSWORD
email-address: EMAIL_ADDRESS
type: Opaque
---
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
service.slack: |
token: $slack-token
service.email.gmail: |
username: $email-username
password: $email-password
host: $email-host
port: $email-port
from: $email-address
template.app-deployed: |
email:
subject: New version of an application {{.app.metadata.name}} is up and running.
message: |
{{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} is now running new version of deployments manifests.
slack:
attachments: |
[{
"title": "{{ .app.metadata.name}}",
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
"color": "#18be52",
"fields": [
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}",
"short": true
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}",
"short": true
},
{
"title": "Revision",
"value": "{{.app.status.sync.revision}}",
"short": true
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}",
"short": true
}
{{end}}
]
}]
template.app-health-degraded: |
email:
subject: Application {{.app.metadata.name}} has degraded.
message: |
{{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} has degraded.
Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}.
slack:
attachments: |-
[{
"title": "{{ .app.metadata.name}}",
"title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
"color": "#f4c030",
"fields": [
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}",
"short": true
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}",
"short": true
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}",
"short": true
}
{{end}}
]
}]
template.app-sync-failed: |
email:
subject: Failed to sync application {{.app.metadata.name}}.
message: |
{{if eq .serviceType "slack"}}:exclamation:{{end}} The sync operation of application {{.app.metadata.name}} has failed at {{.app.status.operationState.finishedAt}} with the following error: {{.app.status.operationState.message}}
Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true .
slack:
attachments: |-
[{
"title": "{{ .app.metadata.name}}",
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
"color": "#E96D76",
"fields": [
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}",
"short": true
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}",
"short": true
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}",
"short": true
}
{{end}}
]
}]
template.app-sync-running: |
email:
subject: Start syncing application {{.app.metadata.name}}.
message: |
The sync operation of application {{.app.metadata.name}} has started at {{.app.status.operationState.startedAt}}.
Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true .
slack:
attachments: |-
[{
"title": "{{ .app.metadata.name}}",
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
"color": "#0DADEA",
"fields": [
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}",
"short": true
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}",
"short": true
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}",
"short": true
}
{{end}}
]
}]
template.app-sync-status-unknown: |
email:
subject: Application {{.app.metadata.name}} sync status is 'Unknown'
message: |
{{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} sync is 'Unknown'.
Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}.
{{if ne .serviceType "slack"}}
{{range $c := .app.status.conditions}}
* {{$c.message}}
{{end}}
{{end}}
slack:
attachments: |-
[{
"title": "{{ .app.metadata.name}}",
"title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
"color": "#E96D76",
"fields": [
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}",
"short": true
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}",
"short": true
}
{{range $index, $c := .app.status.conditions}}
{{if not $index}},{{end}}
{{if $index}},{{end}}
{
"title": "{{$c.type}}",
"value": "{{$c.message}}",
"short": true
}
{{end}}
]
}]
template.app-sync-succeeded: |
email:
subject: Application {{.app.metadata.name}} has been successfully synced.
message: |
{{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} has been successfully synced at {{.app.status.operationState.finishedAt}}.
Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true .
slack:
attachments: "[{\n \"title\": \"{{ .app.metadata.name}}\",\n \"title_link\":\"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}\",\n \"color\": \"#18be52\",\n \"fields\": [\n {\n \"title\": \"Sync Status\",\n \"value\": \"{{.app.status.sync.status}}\",\n \"short\": true\n },\n {\n \"title\": \"Repository\",\n \"value\": \"{{.app.spec.source.repoURL}}\",\n \"short\": true\n }\n {{range $index, $c := .app.status.conditions}}\n {{if not $index}},{{end}}\n {{if $index}},{{end}}\n {\n \"title\": \"{{$c.type}}\",\n \"value\": \"{{$c.message}}\",\n \"short\": true\n }\n {{end}}\n ]\n}] "
trigger.on-deployed: |
- description: Application is synced and healthy. Triggered once per commit.
oncePer: app.status.sync.revision
send:
- app-deployed
when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
trigger.on-health-degraded: |
- description: Application has degraded
send:
- app-health-degraded
when: app.status.health.status == 'Degraded'
trigger.on-sync-failed: |
- description: Application syncing has failed
send:
- app-sync-failed
when: app.status.operationState.phase in ['Error', 'Failed']
trigger.on-sync-running: |
- description: Application is being synced
send:
- app-sync-running
when: app.status.operationState.phase in ['Running']
trigger.on-sync-status-unknown: |
- description: Application status is 'Unknown'
send:
- app-sync-status-unknown
when: app.status.sync.status == 'Unknown'
trigger.on-sync-succeeded: |
- description: Application syncing has succeeded
send:
- app-sync-succeeded
when: app.status.operationState.phase in ['Succeeded']
binaryData: {}

Now apply the configuration via:

kubectl apply -f slackNotifications.yaml