Saturday, June 3, 2023

Kubernetes config and secrets

ConfigMaps

ConfigMaps in Kubernetes are used to store configuration data that can be accessed by applications running within pods. They provide a way to decouple configuration from application code, allowing you to modify the configuration without redeploying the application.

Here are some reasons why ConfigMaps are commonly used in Kubernetes:

  1. Separation of Configuration: ConfigMaps allow you to separate configuration data from your application code. This means you can change the configuration without modifying and redeploying the application. It promotes the "configuration as code" principle, enabling more flexibility and agility in managing your application's configuration.

  2. Environment-specific Configuration: ConfigMaps allow you to create environment-specific configurations. For example, you can have different ConfigMaps for development, staging, and production environments, with each containing the appropriate configuration values for that environment.

  3. Consistency: ConfigMaps help ensure consistency across multiple deployments. By using ConfigMaps, you can provide consistent configuration data to different pods or services running within your cluster.

  4. Dynamic Updates: ConfigMaps can be updated dynamically without restarting the associated pods. When you update a ConfigMap, any pod using that ConfigMap will automatically reflect the updated configuration values. This allows for live configuration updates without interrupting the running application.

  5. Flexible Access: ConfigMaps can be accessed by pods as environment variables or mounted as volumes. This flexibility allows applications to access configuration data in a way that suits their needs. Environment variables are useful for simple key-value configurations, while volume mounts are more suitable for larger configuration files or directories.

  6. Integration with Kubernetes Ecosystem: ConfigMaps can be used in conjunction with other Kubernetes features such as deployments, replica sets, and stateful sets. They can be referenced by other objects in the cluster, making it easy to manage and share configuration across different components.

By leveraging ConfigMaps, you can maintain better control over your application's configuration, promote reusability, and simplify the management of configuration data in a Kubernetes environment.

 

Here's an example of a Deployment in Kubernetes that uses a ConfigMap but need to restart pod/deployment.

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: nginx-config

ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
NGINX_PORT: "80"
NGINX_WORKER_PROCESSES: "2"

Note: To apply the updated configuration, we need to delete the deployment then in new deployment port info will change.

 

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: NGINX_PORT
valueFrom:
configMapKeyRef:
name: nginx-config
key: nginx-port
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx-port: "8080"


 

Here's an example of a Deployment with a ConfigMap that allows for dynamic updates without restarting the pod:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: NGINX_PORT
valueFrom:
configMapKeyRef:
name: nginx-config
key: nginx-port
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx-port: "8080"

 

edit cmd for configmap yaml file

kubectl edit configmap nginx-config


Note :- that the dynamic update of the ConfigMap only applies to certain types of configuration changes, such as environment variables. If other parts of the pod's configuration, such as volume mounts or command arguments, are modified, a pod restart may still be required to apply the changes.

Secrets

In Kubernetes, secrets are used to store and manage sensitive information, such as passwords, API keys, and TLS certificates. Secrets provide a secure way to distribute and manage sensitive data within a cluster. They are typically used by applications or services running in containers to access sensitive information needed for their operation.

Here are some key features and use cases of secrets in Kubernetes:

  1. Secure storage: Secrets are stored securely in the Kubernetes cluster and are encrypted at rest.

  2. Containerized application access: Secrets can be mounted as files or exposed as environment variables inside containers, allowing applications to securely access sensitive information.

  3. Application configuration: Secrets can be used to store configuration data, such as database connection strings or API credentials, which can be accessed by applications during runtime.

  4. Image pull secrets: Secrets can be used to store authentication credentials for private container image repositories, enabling containers to pull images securely.

  5. TLS certificates: Secrets can store TLS certificates and private keys, which can be used for secure communication over HTTPS or other TLS-enabled protocols.

  6. Fine-grained access control: Secrets can be assigned specific permissions to control which users or applications can access them.

By using secrets, Kubernetes ensures that sensitive information is kept secure and separate from other parts of the application's configuration, reducing the risk of accidental exposure or unauthorized access.

Here's an example deployment YAML file that uses a secret and updates the environment variables in the pod without restarting it:

apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp-image
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secrets
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password


In this example, we have a deployment for a containerized application called "myapp". The container image is specified as "myapp-image". The application requires two environment variables, DB_USERNAME and DB_PASSWORD, which will be sourced from a secret named "db-secrets".

To update the values of the DB_USERNAME and DB_PASSWORD without restarting the pod, you can edit the secret directly using the kubectl edit secret command. but note, 1st you must encode it with base64 and then put it in secrets file, For example:

kubectl edit secret db-secrets


apiVersion: v1
kind: Secret
metadata:
name: db-secrets
type: Opaque
data:
username: dXNlcm5hbWU= # Base64 encoded value of the username
password: cGFzc3dvcmQ= # Base64 encoded value of the password

 

cmd for base64 encoding as below

echo -n 'myusername' | base64
echo -n 'mypassword' | base64


cmd for base64 decoding as below

echo "bXlzZWNyZXRwYXNzd29yZA==" | base64 --decode
mysecretpassword



Let's consider a scenario where we have an application that requires an API key to access an external service. We'll store the API key as a secret and mount it as a file inside the pod.

apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: my-app-container
image: my-app-image
volumeMounts:
- name: api-key-volume
mountPath: /etc/my-app
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: my-secrets
key: api-key
volumes:
- name: api-key-volume
secret:
secretName: my-secrets

In this example, we have a pod named "my-app" that runs a container using the "my-app-image" image. The pod is configured to mount the secret "my-secrets" as a volume inside the pod at the path "/etc/my-app". The container's environment variable "API_KEY" is set to the value of the "api-key" key from the secret.

To update the secret and reflect the changes in the pod without restarting it, you can follow these steps:

Edit the secret using the kubectl edit secret command:

kubectl edit secret my-secrets
  1. Modify the value of the "api-key" key to the new API key.

  2. Save the changes and exit the editor.

The updated secret will be automatically propagated to the mounted volume in the pod. The container's environment variable "API_KEY" will reflect the new value without requiring a pod restart. This allows the application inside the pod to access the updated API key in real-time without any disruptions.

 

Different b/w secrets & config map

Secrets and ConfigMaps in Kubernetes are both used to manage and pass configuration data to applications running in pods. However, there are some key differences between them:

  1. Data Sensitivity: Secrets are designed to store sensitive information such as passwords, API keys, and certificates. They are base64 encoded and stored in etcd, the Kubernetes key-value store, in an encrypted format. ConfigMaps, on the other hand, are intended for non-sensitive configuration data.

  2. Data Format: Secrets store data as key-value pairs, just like ConfigMaps. However, Secrets are specifically designed to handle binary data, such as SSL certificates and private keys. ConfigMaps, by default, handle data as plain text.

  3. Data Access: Secrets are mounted as files or environment variables in the pod's file system, making it easy to consume sensitive data in applications. ConfigMaps, too, can be mounted as files or environment variables, but they are typically used for non-sensitive configuration data.

  4. Encryption and Security: Secrets are encrypted at rest and in transit, ensuring the security of sensitive information. ConfigMaps do not provide the same level of encryption and security as Secrets.

Use Secrets for sensitive information and ConfigMaps for non-sensitive configuration data.

 

Deploy an SSL certificate in Kubernetes


you can use the Secret resource to store the certificate and key. Here's an example that demonstrates how to deploy an SSL certificate for an NGINX deployment:

apiVersion: v1
kind: Secret
metadata:
name: tls-secret
data:
tls.crt: <base64-encoded-certificate>
tls.key: <base64-encoded-private-key>
type: kubernetes.io/tls
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 443
volumeMounts:
- name: tls-volume
mountPath: /etc/nginx/certs
readOnly: true
volumes:
- name: tls-volume
secret:
secretName: tls-secret

In this example, we first define a Secret resource named "tls-secret" to store the SSL certificate and private key. The data field contains the base64-encoded values of the certificate and key. Make sure to replace <base64-encoded-certificate> and <base64-encoded-private-key> with the actual base64-encoded values of your SSL certificate and key.

Next, we define a Deployment resource for NGINX. The NGINX container is configured to use port 443, and we mount the tls-secret secret as a volume at the path /etc/nginx/certs. The readOnly option ensures that the certificate and key are accessible to NGINX but cannot be modified from within the container.

To deploy the SSL certificate, save the above YAML configuration to a file (e.g., nginx-ssl.yaml) and apply it using the kubectl apply command:

kubectl apply -f nginx-ssl.yaml 

Kubernetes will create the secret and deploy the NGINX deployment with the SSL certificate. NGINX will be able to use the certificate and key for SSL/TLS encryption.

Note: Remember to replace <base64-encoded-certificate> and <base64-encoded-private-key> with the actual base64-encoded values of your SSL certificate and key. You can encode the certificate and key using the base64 command-line tool:

base64 -w0 certificate.crt
base64 -w0 private.key


Replace certificate.crt and private.key with the actual file names of your certificate and key files.

 

How to check if certificate is Valid ?

Get the details of the Secret that contains the certificate:

kubectl get secret <secret-name> -o yaml

Replace <secret-name> with the actual name of the Secret that contains the certificate.

Extract the certificate and key data from the Secret:

kubectl get secret <secret-name> -o jsonpath='{.data.tls\.crt}' | base64 --decode > certificate.crt
kubectl get secret <secret-name> -o jsonpath='{.data.tls\.key}' | base64 --decode > privatekey.key

These commands will save the certificate and private key data into separate files (certificate.crt and privatekey.key, respectively).

Verify the validity of the certificate:

openssl x509 -in certificate.crt -text -noout

 This command will display detailed information about the certificate, including its validity period, subject, issuer, and other details. Look for the "Validity" section to ensure the certificate is still valid.

Additionally, you can check the certificate's expiration date specifically:

openssl x509 -in certificate.crt -enddate -noout

This command will display the expiration date of the certificate.

By following these steps, you can extract the certificate from the Secret and verify its validity using OpenSSL commands.


How to test certicate after attaching it in Pod/Deployment ?

Once you have attached the certificate in Kubernetes, you can test it by performing an HTTPS request to the relevant service or endpoint using tools like cURL or a web browser. Here's how you can test the certificate:

  1. Identify the hostname or IP address associated with the service or endpoint for which the certificate is attached.

  2. Use cURL to perform an HTTPS request:

    curl --cacert <path-to-certificate> https://<hostname-or-ip-address>

Replace <path-to-certificate> with the path to the certificate file on your local system, and <hostname-or-ip-address> with the actual hostname or IP address associated with the service.

For example:

curl --cacert certificate.crt https://example.com

This command sends an HTTPS request to the specified hostname or IP address, using the provided certificate for verification.

Note: If the certificate is self-signed or from a custom Certificate Authority (CA) that is not trusted by your system, you may need to use the --insecure option with cURL to ignore certificate validation errors:

curl --insecure https://<hostname-or-ip-address>
 
 Analyze the response to determine if the certificate is valid:
  • If the request is successful and you receive the expected response, it indicates that the certificate is valid and properly configured.
  • If you encounter any certificate validation errors or warnings, it suggests that there may be an issue with the certificate, such as expiration, mismatched hostname, or an untrusted CA.

By performing an HTTPS request to the service or endpoint using the attached certificate, you can verify its validity and ensure that it is functioning as expected.

No comments:

Post a Comment