Kubernetes ConfigMap ve Secret Nedir?
Kubernetes ConfigMap ve Secret, uygulamalarınızın yapılandırma bilgilerini ve hassas verilerini güvenli bir şekilde saklamak ve uygulamalarınıza iletmek için kullanılan Kubernetes nesneleridir.
ConfigMap, uygulama yapılandırma bilgilerini depolamak ve paylaşmak için kullanılırken, Secret'ler hassas verileri (parolalar, API anahtarları, sertifikalar vb.) korumak için kullanılır. Bu yazıda, Kubernetes ConfigMap ve Secret kavramlarını daha ayrıntılı olarak ele alacak ve nasıl kullanıldıklarını anlatacağız.
1. ConfigMap Nedir?
ConfigMap, bir uygulamanın yapılandırma bilgilerini key-value çifti şeklinde depolamak için kullanılan bir Kubernetes kaynağıdır. ConfigMap'ler genellikle metin tabanlı verileri içerir. Uygulama pod'larına bu yapılandırma bilgilerini enjekte edebilirsiniz.
ConfigMap içinde oluşturduğunuz key-value configler, bir Pod'a environment variable veya özel bir volume olarak tanımlanabilir. Her birini detaylıca inceleyeceğiz.
Bir uygulamanın bir ConfigMap'i nasıl kullandığından bağımsız olarak, yapılandırmaların ayrı bir bağımsız nesnede olması, Pod manifestinizi değiştirmeden her biri farklı bir ortam için (development, test, QA, production vb.) aynı ada sahip ConfigMaps kullanmanıza olanak tanır. Pod'lar, ConfigMap'e adıyla başvurdukları için, hepsinde aynı Pod manifestini kullanırken her ortamda farklı bir yapılandırma kullanabilirsiniz.
1.1. ConfigMap Nasıl Oluşturulur?
Kubernetes'te ConfigMap oluşturmak için hem YAML hem de kubectl komutunu kullanabilirsiniz. Her iki yönteme de bakalım.
1.1.1 YAML Manifest Dosyasıyla ConfigMap Oluşturmak
YAML manifest dosyasıyla ConfigMap oluşturmak için aşağıdaki örneği kullanabilirsiniz.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
key1: value1
key-2: value2
counter: "5"
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
binaryData:
key3: L3Jvb3QvMTAw
data
parametresi alanında tüm key-value config çiftlerinizi oluşturabilirsiniz.key1
vekey2
property-like key'lerdir.|
işareti ile multi-line configler oluşturabilirsiniz. Bu config tipine file-like key'ler denir.- Eğer değerleriniz UTF-8 olmayan karakterler içeriyorsa
binaryData
parametresi alanında değerlerinizi base64 formatında ekleyebilirsiniz.
Bu YAML dosyasını kullanarak ConfigMap'i oluşturmak için aşağıdaki komutu kullanabilirsiniz:
kubectl apply -f configmap.yaml
1.1.2 Kubectl Komutuyla ConfigMap Oluşturmak
Imperative methodla kubectl komutunu kullanarak ConfigMap oluştururken birçok senaryomuz mevcut. Tüm bu seçeneklere tek tek bakalım.
--from-literal
argümanını kullanarak key-value config oluşturabiliriz. Tek bir komutta birden fazla config oluşturabilirsiniz.
kubectl create configmap my-configmap --from-literal=key1=value1 --from-literal=blog-name="Kerteriz Blog" --from-literal=blog-schema="https://"
--from-file
argümanını kullanarak bir dosya içeriğinden config oluşturabilirsiniz. Eğer key belirtmezseniz, key dosya adı olarak belirlenir.
kubectl create configmap my-configmap --from-file=config-file.conf --from-file=file-config=config-file2.txt
--from-file
argümanını kullanarak sadece dosya değil bir dizinde belirtebilirsiniz. Böylece o dizin altında yer alan tüm dosyalar için configler oluşturulmuş olur.
kubectl create configmap my-configmap --from-file=/var/config-dir/
Son olarak tüm bu yöntemleri tek bir komut içerisinde aynı anda kullanabilirsiniz. Örneğin aşağıdaki komut tüm yöntemleri aynı anda kullanmanıza olanak sağlar.
kubectl create configmap my-config
➥ --from-file=foo.json
➥ --from-file=bar=foobar.conf
➥ --from-file=config-opts/
➥ --from-literal=some=thing
Bu komutu aşağıdaki gibi bir şemaya dökebiliriz.
1.2. ConfigMap Nasıl Kullanılır?
Kubernetes ConfigMap'leri kullanarak bir Pod'un yapılandırma bilgilerini belirtmek için birkaç farklı yöntem vardır. Tüm bu methodları tek tek inceleyelim
1.2.1 Environment Variable Olarak Kullanmak
ConfigMap configlerini kullanmanın en basit yolu, onları environment variable olarak container'lara geçmektir. Pod konfigürasyonunda env
bölümünü kullanarak valueFrom
parametresi ile nasıl environment variable tanımlayabileceğimizi aşağıdaki örnekte görebilirsiniz.
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: my-image
env:
- name: KEY1
valueFrom:
configMapKeyRef:
name: my-configmap
key: key1
- name: KEY2
valueFrom:
configMapKeyRef:
name: my-configmap
key: key2
configMapKeyRef
parametresindeki name
tanımı ile hangi ConfigMap nesnesindeki hangi key'i kullanacağımızı belirtiyoruz.
configMapKeyRef
altına optional: true
eklemelisiniz.Eğer ConfigMap içinde çok fazla config mevcutsa bu şekilde tek tek eklemek zor olacaktır. Bunu çözmek için ConfigMap içindeki tüm configleri envFrom
ile tek seferde environment olarak ayarlayabilirsiniz.
spec:
containers:
- name: my-container
image: my-image
envFrom:
- prefix: CONFIG_
configMapKeyRef:
name: my-configmap
prefix
parametresi opsiyoneldir. Kullandığınızda environment variable eklerken tüm configlerin başına prefix'teki değeri ekler. Eğer ConfigMap içindeki configlerde geçersiz bir environment variable key varsa, örneğin my-key
, bu geçersiz keyler eklenmez ve atlanır. Bu örnekte, environment variable'lar -
karakterini kabul etmediği için eklenmez.
Ayrıca environment variable olarak geçtiğiniz configleri Pod args parametresinde de kullanabilirsiniz.
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: my-image
env:
- name: KEY1
valueFrom:
configMapKeyRef:
name: my-configmap
key: key1
args: ["${KEY1}"]
Aşağıdaki şemada akışı görebilirsiniz.
1.2.2 Config Dosyası Olarak Volume İçinde Kullanmak
Configleri environment variables olarak Pod'lara dahil etmek genelde kısa configler için mantıklıdır. Fakat uzun bir değere sahip (application.properties vb.) configleriniz olduğunda environment variables yerine configMap
kullanmak daha doğru bir yaklaşımdır.
configMap
, ConfigMap içindeki herbir config'i bir dosya olarak belirtilen dizine kaydeder. Örneğin my-nginx-config.conf
ve sleep-interval
isimli dosyalarda config değerleri saklayan configmap-files
isimli bir config dizinimiz mevcut olsun.
my-nginx-config.conf
isimli dosya içerği ise basit bir nginx.conf yapılandırması tutsun.
server {
listen 80;
server_name www.kubia-example.com;
gzip on;
gzip_types text/plain application/xml;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
Bu dizindeki dosyalardan kubectl create configmap fortune-config --from-file=configmap-files
komutu ile kolaylıkla bir ConfigMap oluşturabiliriz.
Ardından bir Pod ile bu configleri kullanabilmek için göreceğiniz üzere environment variable kullanmak mantıklı değildir. Çünkü dosya içeriğimiz çok uzun. Bu nedenle bir configMap
tipinde Config Volume oluşturarak tüm bu configleri ilgili dizine mount edebiliriz.
apiVersion: v1
kind: Pod
metadata:
name: fortune-configmap-volume
spec:
containers:
- image: nginx:alpine
name: web-server
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
readOnly: true
volumes:
- name: config
configMap:
name: fortune-config
Artık Pod oluşturulduğunda fortune-config isimli ConfigMap içindeki tüm configler birer dosya olarak /etc/nginx/conf.d
dizinine mount edilecektir.
Mount ettiğimiz dizinde ls /etc/nginx/conf.d
komutunu çalıştırırsak ConfigMap içinde yer alan iki configi de görebiliriz.
$ ls /etc/nginx/conf.d
my-nginx-config.conf
sleep-interval
Fakat ConfigMap içinde mount ettiğiniz dizine koymak istemeyeceğiniz configler olabilir. Mesela yukarıdaki örnekte sleep-interval
isimli config dosyasının nginx için hiçbir önemi yoktur. Bunun önüne geçebilmek için sadece eklemek istediğiniz configleri aşağıdaki gibi seçebilirsiniz.
volumes:
- name: config
configMap:
name: fortune-config
items:
- key: my-nginx-config.conf
path: nginx.conf
Böylece ConfigMap içinde yer alan sadece my-nginx-config.conf
isimli dosya nginx.conf
dosya ismiyle mount edilen dizine eklenecektir.
Yukarıdaki uyarıdaki davranış Volume'lerin normal davranışıdır. Mount ettiğiniz dizin doluysa, bu dosyalar artık erişilimez hale gelir ve sadece Volume'un içindeki dosyalar gözükür.
Kubernetes ile bunu engellemenin bir yolu mevcuttur. Mount ettiğiniz dizindeki dosyaları erişilimez hale getirmeden subPath
parametresi ile sadece kendi config dosyalarınızı ekleyebilirsiniz.
spec:
containers:
- image: some/image
volumeMounts:
- name: myvolume
mountPath: /etc/someconfig.conf
subPath: myconfig.conf
Bu örnekte, mount edilen dizindeki dosyalar hem erişilebilir halde kalacak, hemde ConfigMap içindeki configinizi ek bir dosya olarak ilgili dizine ekleyebileceksiniz.
Ayrıca config dosyalarınızı mount ederken isterseniz dosya izinlerini de ayarlayabilirsiniz.
volumes:
- name: config
configMap:
name: my-configmap
defaultMode: "6600"
Son olarak tüm volume'u mount ettikten sonra, kubectl edit configmap
komutuyla bir ConfigMap içindeki config değerini güncellediğinizde, mount ettiğiniz dizindeki config dosyasının da içeriği değişir.
Fakat tüm volume yerine subPath ile sadece belirli dosyaları mount ederseniz, ConfigMap değerlerini güncelleseniz bile mount ettiğiniz dizindeki config dosyaları güncellenmeyecektir.
nginx.conf
içeriğini değiştirdikten sonra nginx uygulamasının bu conf değişikliğini algılaması için nginx -s reload
komutunu çalıştırmalısınız.2. Secret Nedir?
Secret, hassas bilgilerin (örneğin, parolalar, API anahtarları, sertifikalar vb.) depolanması ve yönetimi için kullanılan bir Kubernetes nesnesidir. Secret'lar ConfigMap'lerle benzer şekilde çalışır, ancak veriler şifrelenir ve daha güvenli bir şekilde saklanır. Secret'lar da YAML formatında tanımlanır ve genellikle Base64 kodlaması kullanılarak veriler depolanır. Uygulama pod'larına Secret'ları enjekte ederek, bu hassas bilgilere güvenli bir şekilde erişebilirsiniz.
ConfigMap ile Secret arasındaki önemli farklardan birisi Secret'ların bazı tiplere sahip olmasıdır. Bu tiplere şimdi bakalım.
Secret oluştururken type
değeri aşağıdaki değerlerden birini alabilir:
Opaque
:Opaque
(generic
), genel amaçlı bir Secret tipidir ve varsayılan değeridir. Bu tip, herhangi bir metin veya binary veriyi şifrelemeksizin saklamak için kullanılır. Örneğin, parolalar, sertifikalar, özel anahtarlar gibi hassas bilgiler bu Secret tipiyle saklanabilir.kubernetes.io/basic-auth
:basic-auth
, kullanıcı adı ve parolayı saklamak için kullanılan bir Secret tipidir. Bu tip, bir kullanıcının kimlik doğrulama bilgilerini depolamak için kullanılabilir.kubernetes.io/ssh-auth
:ssh-auth
, SSH kimlik doğrulama bilgilerini saklamak için kullanılan bir Secret tipidir. Bu tip, SSH sunucusuna erişim sağlamak için kullanılan kullanıcı adı ve private key bilgilerini içerebilir.kubernetes.io/tls
:tls
, TLS sertifikalarını ve private key'i saklamak için kullanılan bir Secret tipidir. Bu tip, HTTPS trafiğini şifrelemek veya uygulamalar arasında güvenli iletişim sağlamak için kullanılan sertifikaları içerebilir.kubernetes.io/service-account-token
:service-account-token
, Kubernetes Service hesabına ait kimlik bilgilerini içeren bir Secret tipidir. Bu Secret tipi, Kubernetes tarafından otomatik olarak oluşturulur ve Service hesaplarına ilişkin JWT (JSON Web Token) ve diğer yetkilendirme bilgilerini içerir.kubernetes.io/dockercfg
:dockercfg
, Docker Registry'lerine kimlik doğrulama yapmak için kullanılan bir Secret tipidir. Bu tip, Docker imajlarını private registry'den çekmek için gereken kimlik bilgilerini içerebilir.kubernetes.io/dockerconfigjson
:dockerconfigjson
, Docker imajını private registry'den çekmek için kullanılan bir Secret tipidir. Bu tip, Docker Hub veya başka bir özel Docker Registry'sindeki kimlik doğrulama bilgilerini içerir.
Bu type
değerleri, Secret'lerin kullanım amaçlarına göre farklılaşmasını sağlar ve Kubernetes tarafından doğru şekilde yorumlanmalarını sağlar. Secret oluştururken doğru type
değerini belirtmek, Secret'in amacına uygun olarak kullanılmasını sağlar.
2.1. Secret Nasıl Oluşturulur?
Kubernetes'te Secret oluşturmak için hem YAML hem de kubectl komutunu kullanabilirsiniz. Her iki yönteme de bakalım.
2.1.1 YAML Manifest Dosyasıyla Secret Oluşturmak
YAML manifest dosyasıyla Secret oluşturmak için aşağıdaki örneği kullanabilirsiniz.
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: dXNlcm5hbWU=
password: cGFzc3dvcmQ=
stringData:
blog: Kerteriz Blog
data
parametresi alanında tüm key-value config çiftlerinizi oluşturabilirsiniz. Config değerleri Base64 ile encode edilerek eklenmelidir. Çünkü eklemek istediğiniz değerler binary data içeriyor olabilirstringData
parametresi altında ise Base64 yerine plain text değerlerinizi ekleyebilirsiniz.
Bu YAML dosyasını kullanarak Secret'ı oluşturmak için aşağıdaki komutu kullanabilirsiniz:
kubectl apply -f secret.yaml
Diğer Secret tipleri için kullanabileceğiniz manifest örneklerini https://kubernetes.io/docs/concepts/configuration/secret/#secret-types adresinden inceleyebilirsiniz.
2.1.2 Kubectl Komutuyla Secret Oluşturmak
Imperative methodla kubectl komutunu kullanarak Secret oluştururken birçok seçeneğimiz mevcut. Tüm bu seçeneklere tek tek bakalım.
--from-literal
argümanını kullanarak key-value config oluşturabiliriz. Tek bir komutta birden fazla config oluşturabilirsiniz.
kubectl create secret generic my-secret --from-literal=user=poweruser --from-literal=password='f0ob@r'
generic
adını alır.--from-file
argümanını kullanarak bir dosya içeriğinden config oluşturabilirsiniz. Eğer key belirtmezseniz, key dosya adı olarak belirlenir.
kubectl create configmap my-configmap --from-file=config-file.conf --from-file=file-config=config-file2.txt
--from-file
argümanını kullanarak sadece dosya değil bir dizinde belirtebilirsiniz. Böylece o dizin altında yer alan tüm dosyalar için configler oluşturulmuş olur.
kubectl create secret generic my-secret --from-file=/var/secret-config-dir/
Son olarak tüm bu yöntemleri tek bir komut içerisinde aynı anda kullanabilirsiniz. Örneğin aşağıdaki komut tüm yöntemleri aynı anda kullanmanıza olanak sağlar.
kubectl create secret generic my-secret
➥ --from-file=foo.json
➥ --from-file=bar=foobar.conf
➥ --from-file=config-opts/
➥ --from-literal=some=thing
2.2. Secret Nasıl Kullanılır?
Kubernetes Secret'ları kullanarak bir Pod'un yapılandırma bilgilerini belirtmek için birkaç farklı yöntem vardır. Tüm bu methodları tek tek inceleyelim.
2.2.1 Environment Variable Olarak Kullanmak
Secret configlerini kullanmanın en basit yolu, onları environment variable olarak container'lara geçmektir. Pod konfigürasyonunda env
bölümünü kullanarak valueFrom
parametresi ile nasıl environment variable tanımlayabileceğimizi aşağıdaki örnekte görebilirsiniz.
apiVersion: v1
kind: Pod
metadata:
name: my-web
spec:
containers:
- image: nginx
name: web
env:
- name: password
valueFrom:
secretKeyRef:
name: my-secret
key: password
2.2.2 Config Dosyası Olarak Volume İçinde Kullanmak
Configleri environment variables yerine secret
kullanarak bir volume içine de çıkarabilirsiniz.
apiVersion: v1
kind: Pod
metadata:
name: my-web
spec:
containers:
- image: nginx:alpine
name: web-server
volumeMounts:
- name: certs
mountPath: /etc/nginx/certs/
readOnly: true
volumes:
- name: certs
secret:
secretName: my-secret
2.3. Docker Hub Private Repository için Secret Kullanımı
Bu konu ile çok kez karşılaşacağınız için özel bir başlık oluşturduk. Eğer Docker Hub üzerinde yer alan private bir image repository (registry) üzerinden image pull etmeniz gerekirse öncelikle imagePullSecrets
ile gerekli authentication işlemini ayarlamanız gerekir.
Docker registry için Secret tiplerindeki özel docker-registry
tipini kullanacağız. Öncelikle bu tipi kullanarak credentials bilgilerimizi içeren bir secret oluşturalım.
kubectl create secret docker-registry mydockerhubsecret \
--docker-username=myusername --docker-password=mypassword \
--docker-email=my.email@provider.com
generic
tipte bir secret oluşturmak yerine, mydockerhubsecret
adında bir docker-registry
tipinde secret oluşturduk ve Docker Hub kullanıcı adını, şifreni ve e-postasını belirttik. Yeni oluşturulan Secret'ın içeriğini kubectl define ile incelerseniz, .dockercfg
adında tek bir girdi içerdiğini görürsünüz. Bu, ana dizininizdeki docker login
komutunu çalıştırdığınızda Docker tarafından oluşturulan .dockercfg
dosyasına eşdeğerdir.
Artık private repository'den pull edeceğiniz pod'u kullanacağınız manifest dosyasında bu secret'ı imagePullSecrets
değişkeni ile ekleyebilirsiniz:
apiVersion: v1
kind: Pod
metadata:
name: private-pod
spec:
imagePullSecrets:
- name: mydockerhubsecret
containers:
- image: username/private:tag
name: main
Sıradaki yazı ile eğitim serisine devam edebilirsiniz.