البرنامج التعليمي: نشر تطبيق Spring Boot على نظام مجموعة AKS مع قاعدة بيانات Azure ل MySQL - خادم مرن في شبكة ظاهرية

ينطبق على: قاعدة بيانات Azure لـMySQL - خادم مرن

في هذا البرنامج التعليمي، ستتعلم كيفية نشر تطبيق Spring Boot على نظام مجموعة Azure Kubernetes Service (AKS) مع خادم Azure Database for MySQL المرن في الخلفية، والتواصل بأمان مع بعضها البعض داخل شبكة Azure الظاهرية.

إشعار

يفترض هذا البرنامج التعليمي فهماً أساسياً لمفاهيم Kubernetes، Java Spring Boot وMySQL. بالنسبة لتطبيقات Spring Boot، نوصي باستخدام Azure Spring Apps. ومع ذلك، لا يزال بإمكانك استخدام خدمات Azure Kubernetes كوجهة. راجع إرشادات وجهة حمل عمل Java للحصول على المشورة.

المتطلبات الأساسية

إنشاء خادم مرن لـ Azure Database for MySQL

إنشاء مجموعة موارد

مجموعة الموارد عبارة عن حاوية منطقية يتم فيها توزيع موارد Azure وإدارتها. لنقم بإنشاء مجموعة موارد rg-mysqlaksdemo باستخدام الأمر az group create في موقع eastus.

  1. افتح موجه الأوامر.
  2. سجّل الدخول إلى حساب Azure.
    az login
    
  3. اختر مُعرف اشتراك Azure الخاص بك.
    az account set -s <your-subscription-ID>
    
  4. إنشاء مجموعة الموارد.
    az group create --name rg-mysqlaksdemo --location eastus
    

إنشاء مثيل خادم مرن لقاعدة بيانات Azure ل MySQL

سنقوم الآن بإنشاء مثيل خادم مرن لقاعدة بيانات Azure ل MySQL في شبكة ظاهرية (أسلوب اتصال الوصول الخاص).

  1. إنشاء شبكة ظاهرية Azure vnet-mysqlaksdemo لجميع الموارد في هذا البرنامج التعليمي، وشبكة فرعية-mysql لقاعدة بيانات Azure لمثيل خادم MySQL المرن.

    az network vnet create \
    --resource-group rg-mysqlaksdemo \
    --name vnet-mysqlaksdemo \
    --address-prefixes 155.55.0.0/16 \
    --subnet-name subnet-mysql \
    --subnet-prefix 155.55.1.0/24 
    
  2. إنشاء قاعدة بيانات Azure لمثيل خادم MySQL المرن mysql-mysqlaksdemo في الشبكة الفرعية التي تم إنشاؤها أعلاه، باستخدام الأمر az mysql flexible-server create . استبدل قيمك لاسم المستخدم وكلمة المرور للمسؤول.

    az mysql flexible-server create \
    --name mysql-mysqlaksdemo \
    --resource-group rg-mysqlaksdemo \
    --location eastus \
    --admin-user <your-admin-username> \
    --admin-password <your-admin-password> \
    --vnet vnet-mysqlaksdemo \
    --subnet subnet-mysql
    

    لقد قمت الآن بإنشاء مثيل خادم مرن لقاعدة بيانات Azure ل MySQL في منطقة eastus باستخدام حساب B1MS القابل للاندفاع والتخزين بسعة 32 غيغابايت وفترة استبقاء النسخ الاحتياطي لمدة 7 أيام وفي الشبكة الفرعية المتوفرة-mysql. يجب ألّا تحتوي هذه الشبكة الفرعية على أيّ مورد آخر منشور فيها وسيتم تفويضها إلى Microsoft.DBforMySQL/flexibleServers.

  3. تكوين قاعدة بيانات Azure Database جديدة لقاعدة بيانات demo الخادم المرن MySQL لاستخدامها مع تطبيق Spring Boot.

    az mysql flexible-server db create \
    --resource-group rg-mysqlaksdemo \
    --server-name mysql-mysqlaksdemo \
    --database-name demo
    

إنشاء سجل حاويات Azure

إنشاء سجل حاوية Azure خاصة في مجموعة الموارد. يدفع هذا البرنامج التعليمي تطبيق العينة كصورة Docker لهذا السجل في الخطوات اللاحقة. استبدل mysqlaksdemoregistry باسم فريد للسجل الخاص بك.

az acr create --resource-group rg-mysqlaksdemo \
--location eastus \
--name mysqlaksdemoregistry \
--sku Basic

إنشاء التعليمة البرمجية للتطبيق

في هذا القسم، سنقوم بتكوين التعليمات البرمجية لتطبيق العرض التوضيحي. إذا كنت ترغب في الانتقال بشكل أسرع، يمكنك تنزيل التطبيق المُشفر المتوفر في https://github.com/Azure-Samples/tutorial-springboot-mysql-aks والتخطي إلى القسم التالي - إنشاء الصورة والدفع إلى ACR.

  1. إنشاء التطبيق باستخدام Spring Initializr.

    curl https://start.spring.io/starter.tgz \
    -d dependencies=web,data-jdbc,mysql \
    -d baseDir=springboot-mysql-aks \
    -d bootVersion=2.5.6.RELEASE \
    -d artifactId=springboot-mysql-aks \
    -d description="Spring Boot on AKS connecting to Azure DB for MySQL" \
    -d javaVersion=1.8 | tar -xzvf -
    

    سيتم إنشاء تطبيق Spring Boot أساسي داخل springboot-mysql-aks المجلد.

    استخدم محرر نصك المفضل مثل VSCode أو أيّ IDE للخطوات التالية.

  2. تكوين Spring Boot لاستخدام قاعدة بيانات Azure لخادم MySQL المرن.

    افتح الملف src/main/resources/application.properties، وأضف القصاصة البرمجية أدناه. يقرأ هذا الرمز مضيف قاعدة البيانات واسم قاعدة البيانات واسم المستخدم وكلمة المرور من ملف بيان Kubernetes.

    logging.level.org.springframework.jdbc.core=DEBUG
    spring.datasource.url=jdbc:mysql://${DATABASE_HOST}:3306/${DATABASE_NAME}?serverTimezone=UTC
    spring.datasource.username=${DATABASE_USERNAME}
    spring.datasource.password=${DATABASE_PASSWORD}
    spring.datasource.initialization-mode=always
    

    تحذير

    تعني خاصية التكوين spring.datasource.initialization-mode=always أن Spring Boot سيقوم تلقائياً بإنشاء مخطط قاعدة بيانات، باستخدام الملف schema.sql الذي سنقوم بإنشائه لاحقاً، في كل مرة يتم فيها بدء تشغيل الخادم. هذا أمر رائع للاختبار، ولكن تذكر أن هذا سيؤدي إلى حذف بياناتك عند كل إعادة تشغيل، لذلك لا يجب استخدام هذا في الإنتاج!

    إشعار

    نلحق ?serverTimezone=UTC بخاصية التكوين spring.datasource.url، لإخبار برنامج تشغيل JDBC باستخدام تنسيق تاريخ UTC (أو التوقيت العالمي المنسق) عند الاتصال بقاعدة البيانات. خلاف ذلك، لن يستخدم خادم Java الخاص بنا تنسيق التاريخ نفسه مثل قاعدة البيانات، مما قد يؤدي إلى حدوث خطأ.

  3. إنشاء مُخطط قاعدة البيانات.

    سينفذ Spring Boot src/main/resources/schema.sql تلقائياً لإنشاء مُخطط قاعدة بيانات. أنشئ ملفًا جديدًا بالمحتوى التالي:

    DROP TABLE IF EXISTS todo;
    CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);
    
  4. أنشئ تعليمة برمجية لتطبيق Java Spring Boot.

    أضف التعليمة البرمجية لـ Java التي ستستخدم JDBC لتخزين واسترداد البيانات من خادم MySQL. إنشاء Todo فئة Java جديدة، بجانب DemoApplicationالفئة، وإضافة التعليمة البرمجية التالية:

    package com.example.springbootmysqlaks;
    
    import org.springframework.data.annotation.Id;
    
    public class Todo {
    
        public Todo() {
        }
    
        public Todo(String description, String details, boolean done) {
            this.description = description;
            this.details = details;
            this.done = done;
        }
    
        @Id
        private Long id;
    
        private String description;
    
        private String details;
    
        private boolean done;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public String getDetails() {
            return details;
        }
    
        public void setDetails(String details) {
            this.details = details;
        }
    
        public boolean isDone() {
            return done;
        }
    
        public void setDone(boolean done) {
            this.done = done;
        }
    }
    

    هذه الفئة هي نموذج لمجال مُعين في الجدول todo الذي قمت بإنشائه عند تنفيذ البرنامج النصي.

    لإدارة تلك الفئة، ستحتاج إلى مستودع. ضع تعريف واجهة TodoRepository جديدة في الحزمة نفسها:

    package com.example.springbootmysqlaks;
    
    import org.springframework.data.repository.CrudRepository;
    
    public interface TodoRepository extends CrudRepository<Todo, Long> {
    }
    

    هذا المستودع هو المستودع الذي يديره Spring Data JDBC.

    قم بإنهاء التطبيق عن طريق إنشاء وحدة تحكم يمكنها تخزين واسترداد البيانات. نفذ فئة TodoController في نفس الحزمة، وأضف التعليمة البرمجية التالية:

    package com.example.springbootmysqlaks;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping("/")
    public class TodoController {
    
        private final TodoRepository todoRepository;
    
        public TodoController(TodoRepository todoRepository) {
            this.todoRepository = todoRepository;
        }
    
        @PostMapping("/")
        @ResponseStatus(HttpStatus.CREATED)
        public Todo createTodo(@RequestBody Todo todo) {
            return todoRepository.save(todo);
        }
    
        @GetMapping("/")
        public Iterable<Todo> getTodos() {
            return todoRepository.findAll();
        }
    }
    
  5. أنشئ Dockerfile جديداً في الدليل الأساسي springboot-mysql-aks وانسخ القصاصة البرمجية هذه.

    FROM openjdk:8-jdk-alpine
    RUN addgroup -S spring && adduser -S spring -G spring
    USER spring:spring
    ARG DEPENDENCY=target/dependency
    COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
    COPY ${DEPENDENCY}/META-INF /app/META-INF
    COPY ${DEPENDENCY}/BOOT-INF/classes /app
    ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.springbootmysqlaks.DemoApplication"]
    
  6. انتقل إلى ملف pom.xml وحدّث المجموعة <properties> في ملف pom.xml باسم السجل لـAzure Container Registry وأحدث إصدار من jib-maven-plugin. ملاحظة: إذا كان اسم ACR يحتوي على أحرف كبيرة، فتأكد من تحويلها إلى أحرف صغيرة.

    <properties>
     	<docker.image.prefix>mysqlaksdemoregistry.azurecr.io</docker.image.prefix>
     	<jib-maven-plugin.version>3.1.4</jib-maven-plugin.version>
     	<java.version>1.8</java.version>
     </properties>
    
  7. حدّث المجموعة <plugins> في الملف pom.xml بحيث يوجد عنصر <plugin> يحتوي على إدخال لـ jib-maven-plugin، كما هو موضح أدناه. لاحظ أننا نستخدم صورة أساسية من سجل حاوية Microsoft (MCR): mcr.microsoft.com/java/jdk:8-zulu-alpine، الذي يحتوي على مجموعة تطوير Java (JDK) معتمدة رسمياً لـ Azure. للحصول على صور قاعدة MCR أخرى مع JDKs المدعومة رسميا، راجع مركز docker.

    <plugin>
        <artifactId>jib-maven-plugin</artifactId>
        <groupId>com.google.cloud.tools</groupId>
        <version>${jib-maven-plugin.version}</version>
        <configuration>
            <from>
                <image>mcr.microsoft.com/java/jdk:8-zulu-alpine</image>
            </from>
            <to>
                <image>${docker.image.prefix}/${project.artifactId}</image>
            </to>
        </configuration>
    </plugin>
    

تحويل الصورة برمجياً والدفع إلى ACR

في موجه الأوامر، انتقل إلى المجلد springboot-mysql-aks وشغّل الأوامر التالية لتعيين الاسم الافتراضي أولاً لـ Azure Container Registry (وإلّا فستحتاج إلى تحديد الاسم في az acr login)، وبناء الصورة ثم دفع الصورة إلى السجل.

تأكد من تشغيل docker الخفي أثناء تنفيذ هذه الخطوة.

az config set defaults.acr=mysqlaksdemoregistry
az acr login && mvn compile jib:build

إنشاء مجموعة Kubernetes على AKS

سنقوم الآن بإنشاء مجموعة AKS في الشبكة الظاهرية vnet-mysqlaksdemo.

في هذا البرنامج التعليمي، سنستخدم شبكات Azure CNI في AKS. إذا كنت ترغب في تكوين شبكة kubenet بدلاً من ذلك، راجع استخدام شبكة kubenet في AKS.

  1. إنشاء شبكة فرعية subnet-aks لنظام مجموعة AKS لاستخدامها.

    az network vnet subnet create \
    --resource-group rg-mysqlaksdemo \
    --vnet-name vnet-mysqlaksdemo \
    --name subnet-aks \
    --address-prefixes 155.55.2.0/24
    
  2. الحصول على معرف مورد الشبكة الفرعية.

    SUBNET_ID=$(az network vnet subnet show --resource-group rg-mysqlaksdemo --vnet-name vnet-mysqlaksdemo --name subnet-aks --query id -o tsv)
    
  3. إنشاء مجموعة AKS في الشبكة الظاهرية، مع Azure Container Registry (ACR) mysqlaksdemoregistry المُرفقة.

        az aks create \
        --resource-group rg-mysqlaksdemo \
        --name aks-mysqlaksdemo \
        --network-plugin azure \
        --service-cidr 10.0.0.0/16 \
        --dns-service-ip 10.0.0.10 \
        --docker-bridge-address 172.17.0.1/16 \
        --vnet-subnet-id $SUBNET_ID \
        --attach-acr mysqlaksdemoregistry \
        --dns-name-prefix aks-mysqlaksdemo \
        --generate-ssh-keys
    

    يتم تعريف نطاقات عناوين IP التالية أيضًا كجزء من عملية إنشاء نظام المجموعة:

    • يتم استخدام --service-cidr لتعيين عنوان IP للخدمات الداخلية في نظام مجموعة AKS. يمكنك استخدام أي نطاق عناوين خاص يلبي المتطلبات التالية:

      • يجب ألا يكون ضمن نطاق عنوان IP للشبكة الظاهرية من نظام المجموعة
      • يجب أن لا تتداخل مع أية شبكات ظاهرية أخرى مع شبكة الاتصال الظاهري لنظير نظام المجموعة
      • يجب ألا تتداخل مع أي عنواين IPs محلية
      • يجب ألّا تكون ضمن النطاقات 169.254.0.0/16 أو 172.30.0.0/16 أو 172.31.0.0/16 أو 192.0.2.0/24
    • عنوان --dns-service-ip هو عنوان IP لخدمة DNS الخاصة بنظام المجموعة. يجب أن يكون هذا العنوان ضمن نطاق عنوان خدمة Kubernetes. لا تستخدم عنوان IP الأول في نطاق العناوين. يتم استخدام العنوان الأول في نطاق الشبكة الفرعية للعنوان kubernetes.default.svc.cluster.local.

    • --docker-bridge-address: يمثل عنوان شبكة جسر Docker عنوان شبكة جسر docker0 الافتراضي الموجود في جميع عمليات تثبيت Docker. يجب اختيار مساحة عنوان غير متعارضة مع باقي CIDRs على الشبكات الخاصة بك بما في ذلك خدمة نظام المجموعة CIDR ووحدة جراب CIDR.

نشر التطبيق إلى المجموعة AKS

  1. انتقل إلى مورد نظام مجموعة AKS على مدخل Microsoft Azure.

  2. حدد Add وأضف YAML من أيّ من طرق عرض المورد (مساحة الاسم أو أحمال العمل أو الخدمات أو الدخول أو التخزين أو التكوين).

    لقطة شاشة توضح طريقة عرض مورد خدمة Azure Kubernetes على مدخل Microsoft Azure.

  3. الصق في YAML التالي. استبدل قيم Azure Database for MySQL flexible server admin username وكلمة المرور.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: springboot-mysql-aks
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: springboot-mysql-aks
      template:
        metadata:
          labels:
            app: springboot-mysql-aks
        spec:
          containers:
          - name: springboot-mysql-aks
            image: mysqlaksdemoregistry.azurecr.io/springboot-mysql-aks:latest
            env:
            - name: DATABASE_HOST
              value: "mysql-mysqlaksdemo.mysql.database.azure.com"
            - name: DATABASE_USERNAME
              value: "<your-admin-username>"
            - name: DATABASE_PASSWORD
              value: "<your-admin-password>"
            - name: DATABASE_NAME    
              value: "demo"     
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: springboot-mysql-aks
    spec:
      type: LoadBalancer
      ports:
      - port: 80
        targetPort: 8080
      selector:
        app: springboot-mysql-aks
    
  4. حدد Add في الجزء السفلي من محرر YAML لنشر التطبيق.

    لقطة شاشة توضح إضافة باستخدام محرر YAML.

  5. بمجرد إضافة ملف YAML، يعرض عارض الموارد تطبيق Spring Boot الخاص بك. دوّن ملاحظة حول عنوان IP الخارجي المرتبط المُضمن في الخدمة الخارجية.

    لقطة شاشة توضح عرض مدخل Microsoft Azure لعنوان IP الخارجي لخدمة نظام مجموعة Azure Kubernetes.

اختبر التطبيق

لاختبار التطبيق، يمكنك استخدام cURL.

أولاً، قم بإنشاء عنصر "todo" جديد في قاعدة البيانات باستخدام الأمر التالي.

curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"configuration","details":"congratulations, you have deployed your application correctly!","done": "true"}' \
http://<AKS-service-external-ip>

بعد ذلك، قم باسترداد البيانات باستخدام طلب cURL جديد، أو عن طريق إدخال عنوان IP الخارجي للمجموعة في متصفحك.

curl http://<AKS-service-external-ip>

سيقوم هذا الأمر بإرجاع قائمة عناصر "todo"، بما في ذلك العنصر الذي قمت بإنشائه.

[{"id":1,"description":"configuration","details":"congratulations, you have deployed your application correctly!","done":true}]

فيما يلي لقطة شاشة لطلبات cURL هذه: لقطة شاشة تعرض إخراج سطر الأوامر لطلبات cURL.

يمكنك مشاهدة إخراج مشابه من خلال المتصفح الخاص بك: لقطة شاشة تعرض إخراج طلب المستعرض.

تهانينا! لقد نجحت في نشر تطبيق Spring Boot على نظام مجموعة Azure Kubernetes Service (AKS) مع قاعدة بيانات Azure لخادم MySQL المرن في الخلفية!

تفريغ مجموعة الموارد

لتجنب رسوم Azure، يجب تنظيف الموارد غير الضرورية. استخدم الأمر az group deleteلإزالة مجموعة الموارد وخدمة الحاوية، وجميع الموارد ذات الصلة.

az group delete --name rg-mysqlaksdemo

إشعار

عند حذف نظام المجموعة، لا تتم إزالة أساس خدمة Microsoft Entra المستخدم بواسطة نظام مجموعة AKS. للحصول على خطوات حول كيفية إزالة أساس الخدمة، راجع الاعتبارات الأساسية لخدمة AKS وحذفها. في حال استخدمت هوية مُدارة، فستتم إدارة الهوية بواسطة النظام الأساسي ولا تتطلب الإزالة.

الخطوات التالية