نصائح وحيل Kubernetes: الوصول إلى مواقع ديف

نواصل سلسلة من المقالات العملية حول كيفية جعل الحياة أسهل للمطورين والمطورين في عملهم اليومي مع Kubernetes. يتم جمعهم جميعًا من تجربتنا في حل المشكلات من العملاء وتحسينها بمرور الوقت ، ولكن لا يزالون لا يدعون أنهم مثاليون - اعتبرهم أكثر كأفكار وفراغات ، اقترح حلولك وتحسيناتك في التعليقات.


هذه المرة ، سيتم النظر في موضوعين ، مرتبطان مشروطًا بموضوع واحد: وصول المستخدم إلى بيئة التطوير.

1. كيف نغلق دوائر التطوير من المستخدمين غير الضروريين؟


غالبًا ما نواجه مهمة إغلاق دائرة التطوير بالكامل (عشرات / مئات التطبيقات) خلف المصادقة الأساسية أو القائمة البيضاء ، بحيث لا تتمكن روبوتات البحث أو الأشخاص الخارجيون جدًا من الوصول إلى هناك.

عادة ، للحد من الوصول ، يحتاج كل دخول وتطبيق إلى أسرار مصادقة أساسية منفصلة . تعد إدارتها أمرًا صعبًا للغاية عند الكتابة باستخدام عشرات التطبيقات. لذلك ، قمنا بتنظيم التحكم في الوصول المركزي.

للقيام بذلك ، تم إنشاء nginx بتكوين من هذا النوع:

location / { satisfy any; auth_basic "Authentication or whitelist!"; auth_basic_user_file /etc/nginx/htpasswd/htpasswd; allow 10.0.0.0/8; allow 175.28.12.2/32; deny all; try_files FAKE_NON_EXISTENT @return200; } location @return200 { return 200 Ok; } 

علاوة على ذلك ، في بروتوكولات التطبيق ، نقوم ببساطة بإضافة التعليق التوضيحي:

ingress.kubernetes.io/auth-url: "http://dev-auth.dev-auth-infra.svc.cluster.local"

وبالتالي ، عند الوصول إلى التطبيق ، ينتقل الطلب إلى خدمة dev-auth ، التي تتحقق مما إذا تم إدخال المصادقة الأساسية الصحيحة أو يدخل العميل إلى القائمة البيضاء. في حالة استيفاء أحد الشروط ، يتم تأكيد الطلب ويمر إلى التطبيق.



في حالة استخدام مثل هذه الخدمة ، يكفي مستودع واحد ، حيث يتم تخزين قائمة بجميع عمليات الوصول والتي من خلالها يمكننا بسهولة تكوين "مركز التفويض الواحد" الخاص بنا. يتم توزيعه على التطبيقات الجديدة عن طريق الإضافة الأولية للتعليقات التوضيحية.

2. كيف نوفر الوصول إلى التطبيقات داخل Kubernetes في بيئة مطورة؟


... سواء كان Redis أو RabbitMQ أو PostgreSQL أو مطور PHD المفضل لدى Xdebug.

في كثير من الأحيان ، عند ترجمة التطبيقات إلى Kubernetes ، لضمان أمان أفضل ، يتعين علينا حظر الوصول من الخارج وبشكل كامل. ثم يواجه المطورون الذين اعتادوا على "الذهاب IDE" إلى قاعدة البيانات أو Xdebug صعوبات خطيرة.

لحل هذه المشكلة ، نستخدم VPN مباشرة في مجموعة Kubernetes. يبدو المخطط العام بحيث عند الاتصال بخادم VPN يعمل في K8s ، في ملف تكوين OpenVPN ، ندفع عنوان خادم DNS ، الذي يعيش أيضًا في K8s. يقوم OpenVPN بتكوين الشبكة الظاهرية الخاصة بطريقة تجعلها عندما تطلب موردًا داخل Kubernetes ، تذهب أولاً إلى خادم DNS Kubernetes - على سبيل المثال ، خلف عنوان خدمة redis.production.svc.cluster.local . DNS في Kubernetes يحلها إلى 10.244.1.15 وتذهب طلبات عنوان IP هذا عبر OpenVPN مباشرة إلى مجموعة Kubernetes.

خلال تشغيل هذا الحل ، تمكنا من توسيعه بشكل متكرر. على وجه الخصوص:

  1. نظرًا لأننا لم نجد لوحة إدارة بسيطة وكافية (لحالتنا) للمحاسبة للوصول إلى VPN ، كان علينا إنشاء واجهة بسيطة خاصة بنا - يوفر الرسم البياني الرسمي فقط خيار إطلاق أوامر وحدة التحكم لإصدار الشهادات.

    تبدو لوحة الإدارة الناتجة (انظر أيضًا في Docker Hub ) زاهدة جدًا:


    يمكنك إنشاء مستخدمين جدد أو إبطال الشهادات القديمة:


    يمكنك أيضًا مشاهدة التكوين لهذا العميل:

  2. أضفنا المصادقة في VPN بناءً على المستخدمين في GitLab ، حيث يتم التحقق من كلمة المرور وإذا كان المستخدم نشطًا في GitLab. هذا بالنسبة للحالات التي يرغب فيها العميل في إدارة المستخدمين الذين يمكنهم الاتصال بتطوير VPN فقط على أساس GitLab ، وبدون استخدام مشرفين إضافيين - بمعنى ما ، يتحول "SSO للفقراء". كأساس ، أخذوا الرسم البياني الجاهز المذكور بالفعل.

    للقيام بذلك ، كتبنا نص Python النصي الذي يقارن ، عند توصيل مستخدم بـ OpenVPN ، باستخدام اسم المستخدم وكلمة المرور ، التجزئة في قاعدة بيانات GitLab ويتحقق من حالته (سواء كان نشطًا).



    إليك النص نفسه:

     #!/usr/bin/env python3 # pip3 install psycopg2-binary bcrypt import bcrypt import sys import os import psycopg2 import yaml with open("/etc/openvpn/setup/config.yaml", 'r') as ymlfile: cfg = yaml.load(ymlfile) def get_user_info(username=''): try: connect_str = "dbname=%s user=%s host=%s password=%s" % (cfg['db'], cfg['user'], cfg['host'], cfg['pass']) # use our connection values to establish a connection conn = psycopg2.connect(connect_str) # create a psycopg2 cursor that can execute queries cursor = conn.cursor() # create a new table with a single column called "name" cursor.execute("""SELECT encrypted_password,state FROM users WHERE username='%s';""" % username) # run a SELECT statement - no data in there, but we can try it rows = cursor.fetchall() print(rows) return(rows[0]) except Exception as e: print("Uh oh, can't connect. Invalid dbname, user or password?") print(e) def check_user_auth(): username = os.environ['username'] password = bytes(os.environ['password'], 'utf-8') # hashed = bcrypt.hashpw(password, bcrypt.gensalt()) user_info = get_user_info(username=username) user_encrypted_password = bytes(user_info[0], 'utf-8') user_state = True if user_info[1] == 'active' else False if bcrypt.checkpw(password, user_encrypted_password) and user_state: print("It matches!") sys.exit(0) else: print("It does not match :(") sys.exit(1) def main(): check_user_auth() if __name__ == '__main__': main() 

    وفي تكوين OpenVPN ، حدد ما يلي:

    auth-user-pass-verify /etc/openvpn/auth-user.py via-env
    script-security 3
    client-cert-not-required


    وبالتالي ، إذا غادر أحد الموظفين العميل ، فقد قام ببساطة بتعطيله في GitLab ، وبعد ذلك لن يتمكن من الاتصال بشبكة VPN.

بدلا من الاستنتاج


استمرارًا لسلسلة المقالات مع وصفات Flant العملية لتشغيل Kubernetes ، سأغطي مواضيع مثل تسليط الضوء على العقد الفردية لمهام محددة (لماذا وكيف؟) وتكوين خدمات مثل php-fpm / gunicorn تعمل في حاويات للأحمال الثقيلة. اشترك في مدونتنا حتى لا تفوت التحديثات!

ملاحظة


أخرى من دورة النصائح والحيل K8s:


اقرأ أيضا في مدونتنا:

Source: https://habr.com/ru/post/ar427745/


All Articles