Languages: 日本語
This repository provides a modularized configuration using Terraform and GitHub Actions to automatically deploy Azure virtual machines (Ubuntu 22.04 LTS). It supports separation from staging to production environments, enabling safe and gradual deployment.
providers.tf: Provider and Backend configurationvariables.tf: Variable definitionsmain.tf: Main resource definitions (Resource Group + conditional module calls)outputs.tf: Output valuesmodules/network/: Network resource module (for VM)modules/vm/: Virtual machine modulemodules/appservice/: App Service module.github/workflows/plan.yml: Plan workflow (staging environment).github/workflows/apply.yml: Apply workflow (staging environment).github/workflows/apply-production.yml: Apply workflow (production environment).github/workflows/manage-staging.yml: Staging environment management workflow (start/stop/destroy)
- Staging: Staging environment (production-equivalent testing)
- Production: Production environment (full operation)
PR Creation → Plan (Staging) → Review → Merge → Apply (Staging) → Testing → Production Deployment
1. Developer → Create feature branch → Code changes
2. PR Creation → Automatically execute Plan in staging environment
3. Review → Approval → Merge
4. Automatically execute Apply in staging environment
5. Testing in staging environment
6. Manual deployment to production environment (with approval process)
modules/
├── network/
│ ├── main.tf # VNet, Subnet, Public IP, NSG, NIC (for VM)
│ ├── variables.tf # Network module variables
│ └── outputs.tf # Network module outputs
├── vm/
│ ├── main.tf # Linux VM
│ ├── variables.tf # VM module variables
│ └── outputs.tf # VM module outputs
└── appservice/
├── main.tf # App Service Plan & App Service
├── variables.tf # App Service module variables
└── outputs.tf # App Service module outputs
- Azure subscription is required
To use OIDC authentication with GitHub Actions, create an Azure AD application and federation credentials:
# 1. Create Azure AD application
az ad app create --display-name "github-actions-terraform"
# 2. Create service principal
az ad sp create --id <app-id>
# 3. Create federation credentials
az ad app federated-credential create \
--id <app-id> \
--parameters "{\"name\":\"github-actions\",\"issuer\":\"https://token.actions.githubusercontent.com\",\"subject\":\"repo:<your-github-username>/<your-repo-name>:ref:refs/heads/main\",\"audiences\":[\"api://AzureADTokenExchange\"]}"
# 4. Grant necessary permissions
az role assignment create \
--assignee <app-id> \
--role "Contributor" \
--scope /subscriptions/<subscription-id># Login with Azure CLI
az login
# Create App Registration
az ad app create --display-name "GitHub Actions Terraform"
# Get application ID
APP_ID=$(az ad app list --display-name "GitHub Actions Terraform" --query "[].appId" -o tsv)
echo "App ID: $APP_ID"
# Create service principal
az ad sp create --id $APP_ID
# Get service principal ID
SP_ID=$(az ad sp list --display-name "GitHub Actions Terraform" --query "[].id" -o tsv)
echo "Service Principal ID: $SP_ID"# Set GitHub Actions OIDC token issuer
az ad app federated-credential create \
--id $APP_ID \
--parameters "{\"name\":\"github-actions\",\"issuer\":\"https://token.actions.githubusercontent.com\",\"subject\":\"repo:YOUR_GITHUB_USERNAME/YOUR_REPO_NAME:ref:refs/heads/main\",\"audiences\":[\"api://AzureADTokenExchange\"]}"
# Grant permissions to resource group
az role assignment create \
--assignee $SP_ID \
--role "Contributor" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/YOUR_RESOURCE_GROUP_NAME"- Go to GitHub repository
Settings→Environments - Create the following environments with
New environment:stagingproduction
Register the following in repository Settings → Secrets and variables → Actions:
Secrets:
AZURE_CLIENT_ID: Azure AD application client IDAZURE_TENANT_ID: Azure AD tenant IDAZURE_SUBSCRIPTION_ID: Azure subscription IDSSH_PUBLIC_KEY: SSH public key to register with VM
Staging Environment:
TF_VAR_PREFIX: "stg"
AZURE_LOCATION: "japaneast"
RESOURCE_TYPE: "both"
ADMIN_USERNAME: "azureuser"
VM_SIZE: "Standard_B2s"
APP_SERVICE_SKU_TIER: "Standard"
APP_SERVICE_SKU_SIZE: "S1"
Production Environment:
TF_VAR_PREFIX: "prod"
AZURE_LOCATION: "japaneast"
RESOURCE_TYPE: "both"
ADMIN_USERNAME: "azureuser"
VM_SIZE: "Standard_B4ms"
APP_SERVICE_SKU_TIER: "Premium"
APP_SERVICE_SKU_SIZE: "P1v2"
When storing remote state in Azure Storage:
Add to Environment Variables:
BACKEND_RESOURCE_GROUP_NAME: Backend resource group nameBACKEND_STORAGE_ACCOUNT_NAME: Backend storage account nameBACKEND_CONTAINER_NAME: Backend container nameBACKEND_KEY: State file name (default: terraform.tfstate)
- Access control per environment
- Prevention of direct access to production environment
- Environment-specific credential management
- Changes in staging environment don't affect production
- Independent testing per environment
- Gradual deployment
- Resource size optimization per environment
- Environment-specific configuration value management
- Staging and production separation
- Responsibility separation per environment
- Safe parallel development
- Clear review process
# Login with Azure CLI
az login
# Or set authentication credentials with environment variables
export ARM_CLIENT_ID="your-client-id"
export ARM_CLIENT_SECRET="your-client-secret"
export ARM_SUBSCRIPTION_ID="your-subscription-id"
export ARM_TENANT_ID="your-tenant-id"
# Initialize
terraform init
# Execute plan
terraform plan -var="ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"
# Apply
terraform apply -auto-approve -var="ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"- Security: No long-term secrets, authentication with short-term tokens
- Benefits:
- No secret management required
- Automatic token renewal
- Higher security level
- Configuration: Azure AD App Registration integration with GitHub Actions
- Trigger: Pull request creation/update
- Execution Environment: Staging
- Execution Content:
- Format check (
terraform fmt -check) - Validation (
terraform validate) - Plan execution (
terraform plan) - Post results as PR comments
- Format check (
- PR Comment Content:
- PR number and title
- Branch information
- Environment information (Staging)
- Resource type
- Results of each check (with emojis)
- Detailed plan output
- Next steps explanation
- Trigger: Push to main branch
- Execution Environment: Staging
- Execution Content:
- Format check
- Validation
- Plan execution
- Automatic application (
terraform apply)
- Security: State lock functionality prevents simultaneous writes when using backend
- Trigger: Manual execution (workflow_dispatch)
- Execution Environment: Production
- Execution Content:
- Pre-check (approval confirmation)
- Format check
- Validation
- Plan execution
- Application after manual approval (
terraform apply)
- Security:
- Manual approval process required
- Strict production environment control
- Final confirmation by approver
# Initialize
terraform init
# Execute plan
terraform plan -var="resource_type=vm" -var="ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"
# Apply
terraform apply -auto-approve -var="resource_type=vm" -var="ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"# Initialize (with backend configuration)
terraform init \
-backend-config="resource_group_name=tfstate-rg" \
-backend-config="storage_account_name=tfstateaccount123" \
-backend-config="container_name=tfstate" \
-backend-config="key=terraform.tfstate"
# Execute plan
terraform plan -var="resource_type=vm" -var="ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"
# Apply
terraform apply -auto-approve -var="resource_type=vm" -var="ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"Developer → Create feature branch → Code changes → Create PR
↓
Auto-execution: Plan (Staging)
↓
Review → Approval → Merge
↓
Auto-execution: Apply (Staging)
↓
Testing in staging environment
↓
Manual deployment to production environment (with approval process)
- Staging: Production-equivalent resources, integration testing
- Production: Production environment, full operation
- Staging: Accessible by reviewers and above
- Production: Accessible only by administrators, manual approval required
- Deployment completed in staging environment
- Execute testing in staging environment
- Confirm all functions work normally
-
Navigate to GitHub Actions page
- Click
Actionstab in repository
- Click
-
Select Production Deployment Workflow
- Select
Terraform Apply - Production
- Select
-
Execute Workflow
- Click
Run workflowbutton
- Click
-
Set Approval Parameters
Confirm production deployment:trueStaging environment has been verified and tested:trueReason for production deployment: Enter deployment reason
-
Execute Deployment
- Click
Run workflowto execute
- Click
-
Pre-check
- Staging environment verification
- Deployment reason confirmation
- Approver confirmation
-
Plan Execution
- Change content confirmation in production environment
- Detailed resource change confirmation
-
Apply Execution
- Actual deployment after approval
- Change application to production environment
-
Resource Verification
- Resource status confirmation in Azure Portal
- Application operation confirmation
-
Monitoring and Logs
- Application log confirmation
- Performance metrics monitoring
-
Documentation Update
- Deployment history recording
- Configuration change recording
- Deployment completed in staging environment
- Testing successful in staging environment
- Production deployment approved
- Deployment reason clear
- Production Environment Access: Administrators only
- Approval Process: Manual approval required
- Change Tracking: Deployment reason recording
- Audit Logs: Deployment history retention
- Cause: Environment Variables configuration error
- Solution: Check environment variables in GitHub repository Settings
- Cause: OIDC authentication configuration issue
- Solution: Check Azure AD App Registration configuration
- Cause: Environment configuration issue
- Solution: Check GitHub Environments configuration
- Cause: Production environment approval process
- Solution: Contact production environment approver
- Cause: Approval parameter configuration error
- Solution: Set all approval parameters to
true
- Auto-stop: Automatically stop staging environment at 8 PM on weekdays
- Auto-start: Automatically start staging environment at 8 AM on weekdays
- Manual Control: Start/stop/destroy manually as needed
Benefits:
- Resources are retained
- Fast restart
- Data is retained
Drawbacks:
- Some costs continue
- Storage costs occurBenefits:
- Complete cost reduction
- Complete resource removal
- Maximum cost efficiency
Drawbacks:
- Time-consuming recreation
- Data is lost
- Configuration rebuild required- Open Actions tab
- Select Manage Staging Environment
- Click Run workflow
- Select action:
start: Start environmentstop: Stop environmentdestroy: Destroy environment (confirmation required)
After destroying staging environment, recreate using normal deployment workflow:
- Open Actions tab
- Select Terraform Apply
- Click Run workflow
- Deploy to staging environment
# Staging Environment (Low-cost configuration)
VM_SIZE: "Standard_B2s" # ~$0.05/hour
APP_SERVICE_SKU_TIER: "Standard" # ~$0.02/hour
# Production Environment (High-cost configuration)
VM_SIZE: "Standard_B4ms" # ~$0.20/hour
APP_SERVICE_SKU_TIER: "Premium" # ~$0.10/hour- Environment-specific notification settings
- Rollback functionality addition
- Audit log enhancement
- Automated testing integration
- Cost monitoring dashboard
- Auto-scaling functionality
- Terraform Azure Provider
- GitHub Actions Azure Login
- Azure AD OIDC with GitHub Actions
- Azure App Service Documentation
- Terraform App Service Examples
- Terraform: 1.9.0
- AzureRM Provider: ~> 4.40.0