Description for a stopped containers - prometheus-alertmanager

I added a rule into the rules.yml in order to get an alert whenever a container stops.
In order to get an alert for each stopped container with the suffix "dev-23", I used this rule:
- alert: ContainerKilled
expr: absent(container_start_time_seconds{name=~".*dev-23"})
for: 0m
labels:
severity: 'critical'
annotations:
summary: 'Container killed (instance {{ $labels.instance }})'
description: 'A container has disappeared\n VALUE = {{ $value }}\n LABELS: {{ $labels }}'
This indeed works, and I get an alert whenever a container that ends with "dev-23" stops. However, the summary and description of the receieved alert do not tell me what is the name of the stopped container.
In the alert I get this description:
description = A container has disappeared\n VALUE = 1\n LABELS: map[]
summary = Container killed (instance )
What should I use in order to get the exact name of the stopped container?

The issue is, that the metrics created with the absent() function does not have any labels and its value is always 1 (if the queried metric is not present)
You can leave it like that, without any label, if you just want to check if there is NO container running at all, without any details about its previous state and that is enough information to detect the issue.
Or you can use the UP metric, that has the labels, but potentially disappers, e.g. when you have a dynamic service discovery.
In general it a good practice to have an alert on UP{...}==0 and on absent({...})

Related

Argo workflow: schedule once at a specific time

I want to trigger an Argo workflow to start running at a specific time. I am currently using a workflowTemplate and the rest API to submit a workflow with this template. Is there a way to tell Argo to start the workflow at a specific time.
I am aware of the existence of cron-workflow and cron-workflow-template. But I am not able to figure out how to use either workflow or cron-workflow to achieve what I want.
To have any scheduling, do I must use cron-workflow? Or is there a way to trigger a regular workflow at a delay by passing the schedule-time in submitOptions or in some other way through the rest API?
If I must use cron workflow, what should I set the schedule value at? I don't want it to run automatically or periodically, but only when I want and at a specific time. Is there a way achieve that using cronWorkflowTemplate and the rest API?
I will appreciate any help/pointers.
Likely not the answer you're looking for, but if you are able to alter your WorkflowTemplate, you can make the first step be an immediate suspend step, with a value that is provided as an input (by you, when deciding you want to submit the workflow, just not now). For instance, your workflow may look something like this:
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: my-workflow-template
spec:
entrypoint: my-wf
arguments:
parameters:
- name: wait-time-sec
value: "0" # override me
templates:
- name: my-wf
inputs:
parameters:
- name: wait-time-sec
steps:
- - name: wait
template: wait-template
arguments:
parameters:
- name: wait-time-sec
value: "{{inputs.parameters.wait-time-sec}}"
- - name: rest of original workflow steps...
- name: wait-template
inputs:
parameters:
- name: wait-time-sec
suspend:
duration: "{{inputs.parameters.wait-time-sec}}"
...
When you want to submit it, just pass in the parameter wait-time-sec. Granted, if you would rather have a specific time, you would either have to calculate how many seconds that would be before submitting, or write a simple script before the wait step to do that calculation for you, taking in an input of a datetime and outputting seconds for the wait step to use.

How to avoid hardcoded picklist values in Azure pipeline yaml?

Can azure devops pipeline yaml drive picklist values from a file so to avoid hardcoded values in yaml ? Even better allow an api call to dynamically populate a list
Naturally we can roll our own synthesis of pipeline yaml code short of that would be nice if it allowed an include snippets file ability ... one means would be to run a pipeline to generate a pipeline to get run
azure pipeline bad technique today requires a hardcode
parameters:
- name: some_parm
type: string
default: fav_value
values:
- val01
- val02
- val03
what is needed ... populate list dynamically or at a minimum from a file
parameters:
- name: some_parm
type: string
default: fav_value
values:
${{ some_file_or_api_lookup }}
Possibly this yaml preprocessor could work https://github.com/birchb1024/goyamp ... dunno yet
UPDATE 20220906 so far no solution found suggestions welcome

Azure DevOps pipelines for project and deployment specific variables

I am wanting opinion on the following. Have a javascript qna bot that I have in Azure DevOps. I have an azure pipeline created that deploys to an Azure environment. This works well. However, this is a common use bot that can be used in multiple scenarios. Write Once, Use Many. So I want to variabl-ize the process for multiple environments (DEV vs PROD) and instances (PROD1, PROD2, PROD3...)
1st Case: Within the project, there is a .env file with name-value pairs stored. I need to have distinct values for multiple environments and instances. One option could be to have a distinct file per environment+instance. So
.env.DEV, .env.PROD1, .env.PROD2, .env.PROD3, etc.
And then as part of the build process that zips the files, rename only one of the .env files by dropping the suffix based on the case. Can delete the other .env files prior to zipping. Is this a good way to do it OR is there a more standardized process that I should use?
2nd Case: As part of the deployment, I want to variabl-ize the azure-pipeline.yml file so that the target webapp, resource group, subscription, etc are dynamic (different for DEV, PROD1, PROD2, ...). I can create multiple yaml files and link it to separate pipelines. Is this the way? Or am I creating one pipeline and somehow toggling these values for 'n' different cases?
I can hack something. But I wanted to make sure I was using the right approach before starting.
Thanks in advance,
Jake.
1st Case:
Is this a good way to do it OR is there a more standardized process that I should use?
I suggest you can use replace token task to achieve your needs which could be more convenient. Here is my sample:
1.*.env file:
name1:#{value1}#
name2:#{value2}#
name3:#{value3}#
2.Create variables and set values when running the pipeline:
3.Replace token task:
- task: replacetokens#3
inputs:
targetFiles: '**/*.env'
encoding: 'auto'
writeBOM: true
actionOnMissing: 'warn'
keepToken: true
tokenPrefix: '#{'
tokenSuffix: '}#'
useLegacyPattern: false
enableTelemetry: false
4.Result of *.env file:
name1:a
name2:b
name3:c
2nd Case:
I can create multiple yaml files and link it to separate pipelines. Is
this the way? Or am I creating one pipeline and somehow toggling these
values for 'n' different cases?
I suggest you can use parameters and select values when running pipelines. For example:
parameters:
- name: subscription
type: string
default: test1
values:
- test1
- test2
- name: WebAppName
type: string
default: test1
values:
- test1
- test2
- name: ResourceGroupName
type: string
default: test1
values:
- test1
- test2
steps:
- task: AzureAppServiceManage#0
inputs:
azureSubscription: ${{ parameters.subscription }}
Action: 'Stop Azure App Service'
WebAppName: ${{ parameters.WebAppName }}
SpecifySlotOrASE: true
ResourceGroupName: ${{ parameters.ResourceGroupName }}
You can choose the resource group name and subscription name when running pipelins:

How to search by arbitrary fields using field selector with kubectl?

In this doc supported fields are not listed and I cannot find them properly. With some trial and experiments I noticed the following:
This works nicely and finds some pods:
kubectl get pods --field-selector=spec.restartPolicy=Never
But this produces error:
kubectl get pods --field-selector=spec.serviceAccount=default
No resources found.
Error from server (BadRequest): Unable to find {"" "v1" "pods"} that match label selector "", field selector "spec.serviceAccount=default": field label not supported: spec.serviceAccount
So how is this decided? I know I can find with JSONPath but it is client-side filtering AFAIK.
You can select the serviceAccount using following query:
kubectl get pods --field-selector=spec.serviceAccountName="default"
The --field-selector currently selects only equality based values and in that too it has very limited support to select the pod based on fields. The following fields are supported by --field-selector:
metadata.name
metadata.namespace
spec.nodeName
spec.restartPolicy
spec.schedulerName
spec.serviceAccountName
status.phase
status.podIP
status.nominatedNodeName
As you already know, you need to rely on the jsonpath to select any other field other than above fields.
You can visit following link to find out more:
https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/core/v1/conversion.go#L160-L167]1

Cloud Formation Set RDS Endpoint to Route53 CName Record

Below is an example cloud formation file in YAML format. The idea is to make the Route53 Record depend upon creation of the RDS Database and then once its created get the value from the endpoint of the RDS Database.
I did a lot of poking around in these reference documents but kept failing to get the syntax correct.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#aws-properties-rds-database-instance-returnvalues
You can see it should have a return value but I'm not sure how to get it and use it for the route53 cName record name.
resources:
Resources:
uploadBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.uploadBucket}
RDSDatabase:
Type: AWS::RDS::DBInstance
Properties:
Engine : mysql
MasterUsername: ${env:RDS_USERNAME}
MasterUserPassword: ${env:RDS_PASSWORD}
DBInstanceClass : db.t2.micro
AllocatedStorage: '5'
PubliclyAccessible: true
#TODO: The Value of Stage is also available as a TAG automatically which I may use to replace this manually being put here..
Tags:
-
Key: "Name"
Value: ${self:custom.databaseName}
DeletionPolicy: Snapshot
DNSRecordSet:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: mydomain.com.
Name: database-${self:custom.stage}.mydomain.com
Type: CNAME
TTL: '300'
ResourceRecords:
- [[Put End Point Here]]
DependsOn: RDSDatabase
I tried doing this but no luck - ${!Ref RDSDatabase.Endpoint.Address}
An error occurred: DNSRecordSet - Invalid Resource Record: FATAL problem: RRDATANotSingleField (Value contains spaces) encounte
red with '${!Ref RDSDatabase.Endpoint.Address}'.
Found the answer its this...
ResourceRecords:
- {"Fn::GetAtt": ["RDSDatabase","Endpoint.Address"]}
I didn't know I could use the brackets like that in YAML...
Using the !GetAtt short form is even more readable.
ResourceRecords:
- !GetAtt RDSDatabase.Endpoint.Address
What I have done is, I have created an env variable to store the ref to the rds instance endpoint and used it as required
environment:
rdsEndpoint: !GetAtt <Name of the RDS instance>.Endpoint.Address
Now if i wanted to use it i can use it as
const endpoint = process.env.rdsEndpoint

Resources