{"id":344,"date":"2026-09-18T12:00:00","date_gmt":"2026-09-18T12:00:00","guid":{"rendered":"https:\/\/konteynerium.com\/?p=223"},"modified":"2026-10-06T11:34:00","modified_gmt":"2026-10-06T11:34:00","slug":"ansible-ile-sunucu-container-otomasyonu","status":"publish","type":"post","link":"https:\/\/konteynerium.com\/index.php\/2026\/09\/18\/ansible-ile-sunucu-container-otomasyonu\/","title":{"rendered":"Ansible ile Sunucu ve Container Otomasyonu"},"content":{"rendered":"<p>Docker, tek bir uygulamay\u0131 paketlemenin sorununu \u00e7\u00f6zer; ama ger\u00e7ek bir altyap\u0131da onlarca sunucunun her birine Docker&#8217;\u0131 kurmak, g\u00fcvenlik ayarlar\u0131n\u0131 yapmak, kullan\u0131c\u0131lar\u0131 olu\u015fturmak ve container&#8217;lar\u0131 da\u011f\u0131tmak gibi tekrarlayan i\u015fler de vard\u0131r. Bunlar\u0131 elle, sunucu sunucu SSH&#8217;layarak yapmak hem yorucu hem hataya a\u00e7\u0131kt\u0131r. <strong>Ansible<\/strong>, bu t\u00fcr sunucu ve altyap\u0131 otomasyonunu YAML ile tarif edilen, tekrar \u00e7al\u0131\u015ft\u0131r\u0131ld\u0131\u011f\u0131nda hep ayn\u0131 sonucu veren (idempotent) &#8220;playbook&#8221;lar \u00fczerinden \u00e7\u00f6zer.<\/p>\n<h2>Ansible&#8217;\u0131 farkl\u0131 k\u0131lan ne?<\/h2>\n<p>Chef, Puppet gibi di\u011fer otomasyon ara\u00e7lar\u0131n\u0131n aksine Ansible&#8217;\u0131n iki temel \u00f6zelli\u011fi onu \u00f6zellikle yeni ba\u015flayanlar i\u00e7in eri\u015filebilir k\u0131lar:<\/p>\n<ul>\n<li><strong>Agentless (ajans\u0131z):<\/strong> Y\u00f6netti\u011finiz sunuculara herhangi bir yaz\u0131l\u0131m kurman\u0131za gerek yok. Ansible, standart SSH \u00fczerinden ba\u011flan\u0131r ve komutlar\u0131 \u00e7al\u0131\u015ft\u0131r\u0131r; sadece kontrol makinenizde (Ansible&#8217;\u0131n \u00e7al\u0131\u015ft\u0131\u011f\u0131 bilgisayar) Python ve Ansible kurulu olmas\u0131 yeterlidir.<\/li>\n<li><strong>Deklaratif YAML:<\/strong> &#8220;\u015eu ad\u0131mlar\u0131 \u00e7al\u0131\u015ft\u0131r&#8221; yerine &#8220;sunucunun son hali \u015f\u00f6yle olsun&#8221; dersiniz \u2014 Docker&#8217;\u0131n kurulu olmas\u0131, belirli bir kullan\u0131c\u0131n\u0131n var olmas\u0131 gibi. Ansible, o son duruma zaten ula\u015f\u0131lm\u0131\u015fsa hi\u00e7bir \u015fey de\u011fi\u015ftirmez (idempotency) \u2014 playbook&#8217;u g\u00fcvenle defalarca \u00e7al\u0131\u015ft\u0131rabilirsiniz.<\/li>\n<\/ul>\n<h2>Kurulum ve inventory (envanter) dosyas\u0131<\/h2>\n<pre><code># Kontrol makinenize (y\u00f6netilen sunuculara de\u011fil!) kurulum\npip install ansible --break-system-packages\n\nansible --version<\/code><\/pre>\n<p>Ansible&#8217;a hangi sunucular\u0131 y\u00f6netece\u011finizi bir <strong>inventory<\/strong> dosyas\u0131yla s\u00f6ylersiniz:<\/p>\n<pre><code># inventory.ini\n[web]\nweb1.ornek.com\nweb2.ornek.com\n\n[db]\ndb1.ornek.com ansible_user=ubuntu ansible_ssh_private_key_file=~\/.ssh\/prod.pem\n\n[web:vars]\nortam=production<\/code><\/pre>\n<pre><code># T\u00fcm sunuculara SSH ile eri\u015febildi\u011finizi do\u011frulay\u0131n\nansible all -i inventory.ini -m ping<\/code><\/pre>\n<p><code>-m ping<\/code>, Ansible&#8217;\u0131n &#8220;mod\u00fcl&#8221; (module) \u00e7al\u0131\u015ft\u0131rma mant\u0131\u011f\u0131n\u0131n en basit \u00f6rne\u011fidir: her komut asl\u0131nda bir mod\u00fcl\u00fc (<code>ping<\/code>, <code>apt<\/code>, <code>copy<\/code>, <code>docker_container<\/code> gibi) belirtti\u011finiz sunucularda \u00e7al\u0131\u015ft\u0131r\u0131r.<\/p>\n<h2>\u0130lk playbook: sunuculara Docker kurmak<\/h2>\n<pre><code># docker-kur.yml\n---\n- name: Docker Engine'i kur ve yap\u0131land\u0131r\n  hosts: web\n  become: true    # sudo ile \u00e7al\u0131\u015ft\u0131r\n\n  tasks:\n    - name: Gerekli paketleri kur\n      apt:\n        name:\n          - ca-certificates\n          - curl\n          - gnupg\n        state: present\n        update_cache: true\n\n    - name: Docker'\u0131n resmi kurulum beti\u011fini indir\n      get_url:\n        url: https:\/\/get.docker.com\n        dest: \/tmp\/get-docker.sh\n        mode: '0755'\n\n    - name: Docker'\u0131 kur\n      command: sh \/tmp\/get-docker.sh\n      args:\n        creates: \/usr\/bin\/docker    # zaten kuruluysa tekrar \u00e7al\u0131\u015ft\u0131rma\n\n    - name: Kullan\u0131c\u0131y\u0131 docker grubuna ekle\n      user:\n        name: \"{{ ansible_user }}\"\n        groups: docker\n        append: true\n\n    - name: Docker servisinin a\u00e7\u0131l\u0131\u015fta ba\u015flad\u0131\u011f\u0131ndan emin ol\n      systemd:\n        name: docker\n        enabled: true\n        state: started<\/code><\/pre>\n<pre><code>ansible-playbook -i inventory.ini docker-kur.yml<\/code><\/pre>\n<p>Bu playbook&#8217;u <code>web<\/code> grubundaki iki sunucuya kar\u015f\u0131 \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131n\u0131zda, Ansible her g\u00f6revi (task) s\u0131rayla uygular ve zaten o durumda olan bir sunucuda hi\u00e7bir de\u011fi\u015fiklik yapmaz \u2014 \u00e7\u0131kt\u0131da <code>changed<\/code> yerine <code>ok<\/code> g\u00f6r\u00fcrs\u00fcn\u00fcz. Bu, playbook&#8217;u \u00fc\u00e7\u00fcnc\u00fc, d\u00f6rd\u00fcnc\u00fc kez \u00e7al\u0131\u015ft\u0131rmaktan \u00e7ekinmemenizi sa\u011flar.<\/p>\n<div class=\"callout\">\n  <span class=\"glyph\">\u2713<\/span><\/p>\n<p><code>creates: \/usr\/bin\/docker<\/code> sat\u0131r\u0131 idempotency&#8217;nin somut bir \u00f6rne\u011fi: Ansible bu dosya zaten varsa komutu atlar. Elle yazd\u0131\u011f\u0131n\u0131z <code>command<\/code>\/<code>shell<\/code> g\u00f6revlerinde bu t\u00fcr bir koruma eklemek, playbook&#8217;un g\u00fcvenle tekrar \u00e7al\u0131\u015ft\u0131r\u0131labilir kalmas\u0131n\u0131 sa\u011flar.<\/p>\n<\/div>\n<h2>community.docker koleksiyonuyla container da\u011f\u0131tmak<\/h2>\n<p>Ansible&#8217;\u0131n resmi <code>community.docker<\/code> koleksiyonu, <code>docker_container<\/code> ve <code>docker_compose_v2<\/code> gibi mod\u00fcllerle container&#8217;lar\u0131 da do\u011frudan y\u00f6netmenizi sa\u011flar \u2014 sunucu kurulumuyla container da\u011f\u0131t\u0131m\u0131n\u0131 tek bir playbook&#8217;ta birle\u015ftirebilirsiniz:<\/p>\n<pre><code>ansible-galaxy collection install community.docker<\/code><\/pre>\n<pre><code># container-dagit.yml\n---\n- name: Uygulama container'\u0131n\u0131 da\u011f\u0131t\n  hosts: web\n  become: true\n\n  tasks:\n    - name: En g\u00fcncel imaj\u0131 \u00e7ek\n      community.docker.docker_image:\n        name: kullanici-adi\/benim-api\n        tag: latest\n        source: pull\n        force_source: true\n\n    - name: Container'\u0131 (yoksa) olu\u015ftur, (varsa) g\u00fcnceltilmi\u015f imajla yeniden ba\u015flat\n      community.docker.docker_container:\n        name: benim-api\n        image: kullanici-adi\/benim-api:latest\n        state: started\n        restart_policy: unless-stopped\n        recreate: true\n        ports:\n          - \"8080:8080\"\n        env:\n          DATABASE_URL: \"{{ vault_database_url }}\"<\/code><\/pre>\n<p>Buradaki <code>vault_database_url<\/code> de\u011fi\u015fkeni, gizli bilgilerin playbook&#8217;a a\u00e7\u0131k metin olarak yaz\u0131lmas\u0131n\u0131 \u00f6nlemek i\u00e7in <strong>Ansible Vault<\/strong> ile \u015fifrelenmi\u015f bir dosyadan gelir (<code>ansible-vault create secrets.yml<\/code>) \u2014 t\u0131pk\u0131 Docker&#8217;da secret&#8217;lar\u0131 imaja g\u00f6mmemek gerekti\u011fi gibi, Ansible playbook&#8217;lar\u0131nda da parolalar asla d\u00fcz metin tutulmamal\u0131d\u0131r.<\/p>\n<h2>Roller: playbook&#8217;lar\u0131 yeniden kullan\u0131labilir hale getirmek<\/h2>\n<p>Playbook&#8217;lar b\u00fcy\u00fcd\u00fck\u00e7e, ilgili g\u00f6revleri, dosyalar\u0131 ve varsay\u0131lan de\u011fi\u015fkenleri bir arada tutan <strong>role<\/strong> (rol) yap\u0131s\u0131na ge\u00e7ilir \u2014 t\u0131pk\u0131 bir Docker imaj\u0131n\u0131 farkl\u0131 projelerde yeniden kullanmak gibi, bir Ansible rol\u00fcn\u00fc de (\u00f6rne\u011fin &#8220;docker-kurulumu&#8221; rol\u00fc) farkl\u0131 projelerde tekrar tekrar kullanabilirsiniz:<\/p>\n<pre><code>ansible-galaxy init roles\/docker-kurulumu<\/code><\/pre>\n<pre><code>roles\/\n  docker-kurulumu\/\n    tasks\/main.yml       # yukar\u0131daki g\u00f6revler buraya ta\u015f\u0131n\u0131r\n    handlers\/main.yml    # \u00f6rn. \"docker'\u0131 yeniden ba\u015flat\" gibi tetiklenen eylemler\n    defaults\/main.yml    # varsay\u0131lan de\u011fi\u015fkenler\n    templates\/           # Jinja2 \u015fablonlar\u0131 (\u00f6rn. daemon.json)<\/code><\/pre>\n<pre><code># site.yml \u2014 rolleri birle\u015ftiren ana playbook\n---\n- hosts: web\n  become: true\n  roles:\n    - docker-kurulumu\n    - uygulama-dagitimi<\/code><\/pre>\n<h2>Ansible, Docker Compose ve Kubernetes ile nas\u0131l bir arada durur?<\/h2>\n<table>\n<thead>\n<tr>\n<th>Ara\u00e7<\/th>\n<th>Hangi katman\u0131 y\u00f6netir?<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Dockerfile<\/td>\n<td>Tek bir imaj\u0131n i\u00e7eri\u011fi<\/td>\n<\/tr>\n<tr>\n<td>Docker Compose<\/td>\n<td>Tek sunucuda birden fazla container&#8217;\u0131n birlikte \u00e7al\u0131\u015fmas\u0131<\/td>\n<\/tr>\n<tr>\n<td><strong>Ansible<\/strong><\/td>\n<td>Sunucular\u0131n kendisi: paket kurulumu, kullan\u0131c\u0131lar, g\u00fcvenlik ayarlar\u0131, birden fazla sunucuya tutarl\u0131 da\u011f\u0131t\u0131m<\/td>\n<\/tr>\n<tr>\n<td>Kubernetes<\/td>\n<td>Container&#8217;lar\u0131n bir k\u00fcmede orkestrasyonu, \u00f6l\u00e7ekleme, self-healing<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Bu ara\u00e7lar birbirini d\u0131\u015flamaz, farkl\u0131 sorunlar\u0131 \u00e7\u00f6zer. Yayg\u0131n bir ger\u00e7ek d\u00fcnya deseni: Ansible ile sunucular\u0131 (veya Kubernetes node&#8217;lar\u0131n\u0131n kendisini) haz\u0131rlamak, Docker Compose veya Kubernetes ile \u00fczerlerindeki uygulamalar\u0131 \u00e7al\u0131\u015ft\u0131rmak.<\/p>\n<p>Sunucular\u0131n\u0131z art\u0131k kod olarak, tutarl\u0131 ve tekrarlanabilir \u015fekilde yap\u0131land\u0131r\u0131l\u0131yor. Bir ad\u0131m daha geriye gidip, bu sunucular\u0131n kendisinin (bulut sa\u011flay\u0131c\u0131da bir VM, a\u011f, g\u00fcvenlik grubu) nas\u0131l otomatik olarak <em>olu\u015fturulaca\u011f\u0131n\u0131<\/em> ele almak i\u00e7in s\u0131rada Terraform ile altyap\u0131y\u0131 kodlama var.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ajans\u0131z, idempotent playbook&#8217;larla onlarca sunucuya tutarl\u0131 \u015fekilde Docker kurmaktan community.docker koleksiyonuyla container da\u011f\u0131tmaya, rollere kadar Ansible&#8217;\u0131 s\u0131f\u0131rdan \u00f6\u011frenin.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"seviye":[8],"class_list":["post-344","post","type-post","status-publish","format-standard","hentry","category-production-uygulamalar","seviye-orta"],"_links":{"self":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/344","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/comments?post=344"}],"version-history":[{"count":1,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/344\/revisions"}],"predecessor-version":[{"id":582,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/344\/revisions\/582"}],"wp:attachment":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/media?parent=344"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/categories?post=344"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/tags?post=344"},{"taxonomy":"seviye","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/seviye?post=344"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}